diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 882f0e1..2c05670 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -164,10 +164,6 @@ - - - - diff --git a/imgui-binding/src/main/java/imgui/ImDestroyable.java b/imgui-binding/src/main/java/imgui/ImDestroyable.java new file mode 100644 index 0000000..71c1ae7 --- /dev/null +++ b/imgui-binding/src/main/java/imgui/ImDestroyable.java @@ -0,0 +1,9 @@ +package imgui; + +/** + * While implementing this interface, class could be manually destroyed (free allocated memory on the JNI side). + * Read javadoc and "BINDING NOTICE" for specific cases. + */ +interface ImDestroyable { + void destroy(); +} diff --git a/imgui-binding/src/main/java/imgui/ImDrawData.java b/imgui-binding/src/main/java/imgui/ImDrawData.java index c4e22f7..4176da8 100644 --- a/imgui-binding/src/main/java/imgui/ImDrawData.java +++ b/imgui-binding/src/main/java/imgui/ImDrawData.java @@ -6,6 +6,7 @@ import java.nio.ByteOrder; /** * All draw data to render a Dear ImGui frame. + *

* BINDING NOTICE: DO NOT TRY TO MODIFY FIELDS OF THIS CLASS MANUALLY! You should only access their values after {@link ImGui#render()} call. */ public final class ImDrawData { diff --git a/imgui-binding/src/main/java/imgui/ImFont.java b/imgui-binding/src/main/java/imgui/ImFont.java new file mode 100644 index 0000000..0a784e9 --- /dev/null +++ b/imgui-binding/src/main/java/imgui/ImFont.java @@ -0,0 +1,203 @@ +package imgui; + +/** + * Font runtime data and rendering + * ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32(). + */ +public final class ImFont implements ImDestroyable { + final long ptr; + + private ImFontGlyph fallbackGlyph = null; + + /** + * This class will create a native structure. + * Call {@link #destroy()} method to manually free used memory. + */ + public ImFont() { + ImGui.touch(); + ptr = nCreate(); + } + + ImFont(final long ptr) { + this.ptr = ptr; + } + + @Override + public void destroy() { + nDestroy(ptr); + } + + /*JNI + #include + #include "jni_common.h" + + jfieldID imFontPtrID; + + #define IM_FONT ((ImFont*)env->GetLongField(object, imFontPtrID)) + */ + + static native void nInit(); /* + jclass jImFontClass = env->FindClass("imgui/ImFont"); + imFontPtrID = env->GetFieldID(jImFontClass, "ptr", "J"); + */ + + private native long nCreate(); /* + ImFont* imFont = new ImFont(); + return (long)imFont; + */ + + private native void nDestroy(long ptr); /* + delete (ImFont*)ptr; + */ + + // TODO IndexAdvanceX + + /** + * = FallbackGlyph->AdvanceX + */ + public native float getFallbackAdvanceX(); /* + return IM_FONT->FallbackAdvanceX; + */ + + /** + * = FallbackGlyph->AdvanceX + */ + public native void setFallbackAdvanceX(float fallbackAdvanceX); /* + IM_FONT->FallbackAdvanceX = fallbackAdvanceX; + */ + + /** + * Height of characters/line, set during loading (don't change after loading) + */ + public native float getFontSize(); /* + return IM_FONT->FontSize; + */ + + // TODO IndexLookup, Glyphs + + /** + * = FindGlyph(FontFallbackChar) + */ + public ImFontGlyph getFallbackGlyph() { + if (fallbackGlyph == null) { + fallbackGlyph = new ImFontGlyph(nGetFallbackGlyphPtr()); + } + return fallbackGlyph; + } + + private native long nGetFallbackGlyphPtr(); /* + return (long)IM_FONT->FallbackGlyph; + */ + + /** + * Offset font rendering by xx pixels + */ + public native void getDisplayOffset(ImVec2 dstImVec2); /* + Jni::ImVec2Cpy(env, &IM_FONT->DisplayOffset, dstImVec2); + */ + + /** + * Offset font rendering by xx pixels + */ + public native void setDisplayOffset(float x, float y); /* + IM_FONT->DisplayOffset.x = x; + IM_FONT->DisplayOffset.y = y; + */ + + // TODO ContainerAtlas, ConfigData + + /** + * Number of ImFontConfig involved in creating this font. + * Bigger than 1 when merging multiple font sources into one ImFont. + */ + public native short getConfigDataCount(); /* + return IM_FONT->ConfigDataCount; + */ + + /** + * Replacement character if a glyph isn't found. + */ + public native short getFallbackChar(); /* + return IM_FONT->FallbackChar; + */ + + /** + * Character used for ellipsis rendering. + */ + public native short getEllipsisChar(); /* + return IM_FONT->EllipsisChar; + */ + + /** + * Character used for ellipsis rendering. + */ + public native void setEllipsisChar(short ellipsisChar); /* + IM_FONT->EllipsisChar = (ImWchar)ellipsisChar; + */ + + /** + * Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() + */ + public native float getScale(); /* + return IM_FONT->Scale; + */ + + /** + * Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() + */ + public native void setScale(float scale); /* + IM_FONT->Scale = scale; + */ + + /** + * Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] + */ + public native float getAscent(); /* + return IM_FONT->Ascent; + */ + + /** + * Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] + */ + public native void setAscent(float ascent); /* + IM_FONT->Ascent = ascent; + */ + + /** + * Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] + */ + public native float getDescent(); /* + return IM_FONT->Descent; + */ + + /** + * Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] + */ + public native void setDescent(float descent); /* + IM_FONT->Descent = descent; + */ + + /** + * Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) + */ + public native int getMetricsTotalSurface(); /* + return IM_FONT->MetricsTotalSurface; + */ + + /** + * Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) + */ + public native void setMetricsTotalSurface(int metricsTotalSurface); /* + IM_FONT->MetricsTotalSurface = metricsTotalSurface; + */ + + public native boolean getDirtyLookupTables(); /* + return IM_FONT->DirtyLookupTables; + */ + + public native void setDirtyLookupTables(boolean dirtyLookupTables); /* + IM_FONT->DirtyLookupTables = dirtyLookupTables; + */ + + // TODO methods +} diff --git a/imgui-binding/src/main/java/imgui/ImFontAtlas.java b/imgui-binding/src/main/java/imgui/ImFontAtlas.java new file mode 100644 index 0000000..a526531 --- /dev/null +++ b/imgui-binding/src/main/java/imgui/ImFontAtlas.java @@ -0,0 +1,548 @@ +package imgui; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * Load and rasterize multiple TTF/OTF fonts into a same texture. The font atlas will build a single texture holding: + * - One or more fonts. + * - Custom graphics data needed to render the shapes needed by Dear ImGui. + * - Mouse cursor shapes for software cursor rendering (unless setting 'Flags |= ImFontAtlasFlags_NoMouseCursors' in the font atlas). + * It is the user-code responsibility to setup/build the atlas, then upload the pixel data into a texture accessible by your graphics api. + * - Optionally, call any of the AddFont*** functions. If you don't call any, the default font embedded in the code will be loaded for you. + * - Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data. + * - Upload the pixels data into a texture within your graphics system (see imgui_impl_xxxx.cpp examples) + * - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API. + * This value will be passed back to you during rendering to identify the texture. Read FAQ entry about ImTextureID for more details. + * Common pitfalls: + * - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the + * atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data. + * - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction. + * You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed, + * - Even though many functions are suffixed with "TTF", OTF data is supported just as well. + * - This is an old API and it is currently awkward for those and and various other reasons! We will address them in the future! + */ +public final class ImFontAtlas implements ImDestroyable { + final long ptr; + + /** + * This class will create a native structure. + * Call {@link #destroy()} method to manually free used memory. + */ + public ImFontAtlas() { + ImGui.touch(); + ptr = nCreate(); + } + + ImFontAtlas(final long ptr) { + this.ptr = ptr; + } + + @Override + public void destroy() { + nDestroy(ptr); + } + + /*JNI + #include + + jfieldID imFontAtlasPtrID; + + #define IM_FONT_ATLAS ((ImFontAtlas*)env->GetLongField(object, imFontAtlasPtrID)) + */ + + static native void nInit(); /* + jclass jImFontAtlasClass = env->FindClass("imgui/ImFontAtlas"); + imFontAtlasPtrID = env->GetFieldID(jImFontAtlasClass, "ptr", "J"); + */ + + private native long nCreate(); /* + ImFontAtlas* imFontAtlas = new ImFontAtlas(); + return (long)imFontAtlas; + */ + + private native void nDestroy(long ptr); /* + delete (ImFontAtlas*)ptr; + */ + + public ImFont addFont(final ImFontConfig imFontConfig) { + return new ImFont(nAddFont(imFontConfig.ptr)); + } + + private native long nAddFont(long imFontConfigPtr); /* + return (long)IM_FONT_ATLAS->AddFont((ImFontConfig*)imFontConfigPtr); + */ + + public ImFont addFontDefault() { + return new ImFont(nAddFontDefault()); + } + + private native long nAddFontDefault(); /* + return (long)IM_FONT_ATLAS->AddFontDefault(); + */ + + public ImFont addFontDefault(final ImFontConfig imFontConfig) { + return new ImFont(nAddFontDefault(imFontConfig.ptr)); + } + + private native long nAddFontDefault(long imFontConfigPtr); /* + return (long)IM_FONT_ATLAS->AddFontDefault((ImFontConfig*)imFontConfigPtr); + */ + + public ImFont addFontFromFileTTF(final String filename, final float sizePixels) { + return new ImFont(nAddFontFromFileTTF(filename, sizePixels)); + } + + private native long nAddFontFromFileTTF(String filename, float sizePixels); /* + return (long)IM_FONT_ATLAS->AddFontFromFileTTF(filename, sizePixels); + */ + + public ImFont addFontFromFileTTF(final String filename, final float sizePixels, final ImFontConfig imFontConfig) { + return new ImFont(nAddFontFromFileTTF(filename, sizePixels, imFontConfig.ptr)); + } + + private native long nAddFontFromFileTTF(String filename, float sizePixels, long imFontConfigPtr); /* + return (long)IM_FONT_ATLAS->AddFontFromFileTTF(filename, sizePixels, (ImFontConfig*)imFontConfigPtr); + */ + + public ImFont addFontFromFileTTF(final String filename, final float sizePixels, final short[] glyphRanges) { + return new ImFont(nAddFontFromFileTTF(filename, sizePixels, glyphRanges)); + } + + private native long nAddFontFromFileTTF(String filename, float sizePixels, short[] glyphRanges); /* + return (long)IM_FONT_ATLAS->AddFontFromFileTTF(filename, sizePixels, NULL, (ImWchar*)&glyphRanges[0]); + */ + + public ImFont addFontFromFileTTF(final String filename, final float sizePixels, final ImFontConfig imFontConfig, final short[] glyphRanges) { + return new ImFont(nAddFontFromFileTTF(filename, sizePixels, imFontConfig.ptr, glyphRanges)); + } + + private native long nAddFontFromFileTTF(String filename, float sizePixels, long imFontConfigPtr, short[] glyphRanges); /* + return (long)IM_FONT_ATLAS->AddFontFromFileTTF(filename, sizePixels, (ImFontConfig*)imFontConfigPtr, (ImWchar*)&glyphRanges[0]); + */ + + /** + * Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. + * Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed. + */ + public ImFont addFontFromMemoryTTF(final byte[] fontData, final float sizePixels) { + return new ImFont(nAddFontFromMemoryTTF(fontData, fontData.length, sizePixels)); + } + + private native long nAddFontFromMemoryTTF(byte[] fontData, int fontSize, float sizePixels); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryTTF(&fontData[0], fontSize, sizePixels); + */ + + + /** + * Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. + * Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed. + */ + public ImFont addFontFromMemoryTTF(final byte[] fontData, final float sizePixels, final ImFontConfig imFontConfig) { + return new ImFont(nAddFontFromMemoryTTF(fontData, fontData.length, sizePixels, imFontConfig.ptr)); + } + + private native long nAddFontFromMemoryTTF(byte[] fontData, int fontSize, float sizePixels, long imFontConfigPtr); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryTTF(&fontData[0], fontSize, sizePixels, (ImFontConfig*)imFontConfigPtr); + */ + + /** + * Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. + * Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed. + */ + public ImFont addFontFromMemoryTTF(final byte[] fontData, final float sizePixels, final short[] glyphRanges) { + return new ImFont(nAddFontFromMemoryTTF(fontData, fontData.length, sizePixels, glyphRanges)); + } + + private native long nAddFontFromMemoryTTF(byte[] fontData, int fontSize, float sizePixels, short[] glyphRanges); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryTTF(&fontData[0], fontSize, sizePixels, NULL, (ImWchar*)&glyphRanges[0]); + */ + + /** + * Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. + * Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed. + */ + public ImFont addFontFromMemoryTTF(final byte[] fontData, final float sizePixels, final ImFontConfig imFontConfig, final short[] glyphRanges) { + return new ImFont(nAddFontFromMemoryTTF(fontData, fontData.length, sizePixels, imFontConfig.ptr, glyphRanges)); + } + + private native long nAddFontFromMemoryTTF(byte[] fontData, int fontSize, float sizePixels, long imFontConfigPtr, short[] glyphRanges); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryTTF(&fontData[0], fontSize, sizePixels, (ImFontConfig*)imFontConfigPtr, (ImWchar*)&glyphRanges[0]); + */ + + /** + * 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. + */ + public ImFont addFontFromMemoryCompressedTTF(final byte[] compressedFontData, final float sizePixels) { + return new ImFont(nAddFontFromMemoryCompressedTTF(compressedFontData, compressedFontData.length, sizePixels)); + } + + private native long nAddFontFromMemoryCompressedTTF(byte[] compressedFontData, int fontSize, float sizePixels); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryCompressedTTF(&compressedFontData[0], fontSize, sizePixels); + */ + + /** + * 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. + */ + public ImFont addFontFromMemoryCompressedTTF(final byte[] compressedFontData, final float sizePixels, final ImFontConfig imFontConfig) { + return new ImFont(nAddFontFromMemoryCompressedTTF(compressedFontData, compressedFontData.length, sizePixels, imFontConfig.ptr)); + } + + private native long nAddFontFromMemoryCompressedTTF(byte[] compressedFontData, int fontSize, float sizePixels, long imFontConfigPtr); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryCompressedTTF(&compressedFontData[0], fontSize, sizePixels, (ImFontConfig*)imFontConfigPtr); + */ + + /** + * 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. + */ + public ImFont addFontFromMemoryCompressedTTF(final byte[] compressedFontData, final float sizePixels, final short[] glyphRanges) { + return new ImFont(nAddFontFromMemoryCompressedTTF(compressedFontData, compressedFontData.length, sizePixels, glyphRanges)); + } + + private native long nAddFontFromMemoryCompressedTTF(byte[] compressedFontData, int fontSize, float sizePixels, short[] glyphRanges); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryCompressedTTF(&compressedFontData[0], fontSize, sizePixels, NULL, (ImWchar*)&glyphRanges[0]); + */ + + /** + * 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. + */ + public ImFont addFontFromMemoryCompressedTTF(final byte[] compressedFontData, final float sizePixels, final ImFontConfig imFontConfig, final short[] glyphRanges) { + return new ImFont(nAddFontFromMemoryCompressedTTF(compressedFontData, compressedFontData.length, sizePixels, imFontConfig.ptr, glyphRanges)); + } + + private native long nAddFontFromMemoryCompressedTTF(byte[] compressedFontData, int fontSize, float sizePixels, long imFontConfigPtr, short[] glyphRanges); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryCompressedTTF(&compressedFontData[0], fontSize, sizePixels, (ImFontConfig*)imFontConfigPtr, (ImWchar*)&glyphRanges[0]); + */ + + /** + * 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. + */ + public ImFont addFontFromMemoryCompressedBase85TTF(final String compressedFontDataBase85, final float sizePixels) { + return new ImFont(nAddFontFromMemoryCompressedBase85TTF(compressedFontDataBase85, sizePixels)); + } + + private native long nAddFontFromMemoryCompressedBase85TTF(String compressedFontDataBase85, float sizePixels); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryCompressedBase85TTF(compressedFontDataBase85, sizePixels); + */ + + /** + * 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. + */ + public ImFont addFontFromMemoryCompressedBase85TTF(final String compressedFontDataBase85, final float sizePixels, final ImFontConfig imFontConfig) { + return new ImFont(nAddFontFromMemoryCompressedBase85TTF(compressedFontDataBase85, sizePixels, imFontConfig.ptr)); + } + + private native long nAddFontFromMemoryCompressedBase85TTF(String compressedFontDataBase85, float sizePixels, long imFontConfigPtr); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryCompressedBase85TTF(compressedFontDataBase85, sizePixels, (ImFontConfig*)imFontConfigPtr); + */ + + /** + * 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. + */ + public ImFont addFontFromMemoryCompressedBase85TTF(final String compressedFontDataBase85, final float sizePixels, final short[] glyphRanges) { + return new ImFont(nAddFontFromMemoryCompressedBase85TTF(compressedFontDataBase85, sizePixels, glyphRanges)); + } + + private native long nAddFontFromMemoryCompressedBase85TTF(String compressedFontDataBase85, float sizePixels, short[] glyphRanges); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryCompressedBase85TTF(compressedFontDataBase85, sizePixels, NULL, (ImWchar*)&glyphRanges[0]); + */ + + /** + * 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. + */ + public ImFont addFontFromMemoryCompressedBase85TTF(final String compressedFontDataBase85, final float sizePixels, final ImFontConfig imFontConfig, final short[] glyphRanges) { + return new ImFont(nAddFontFromMemoryCompressedBase85TTF(compressedFontDataBase85, sizePixels, imFontConfig.ptr, glyphRanges)); + } + + private native long nAddFontFromMemoryCompressedBase85TTF(String compressedFontDataBase85, float sizePixels, long imFontConfigPtr, short[] glyphRanges); /* + return (long)IM_FONT_ATLAS->AddFontFromMemoryCompressedBase85TTF(compressedFontDataBase85, sizePixels, (ImFontConfig*)imFontConfigPtr, (ImWchar*)&glyphRanges[0]); + */ + + /** + * Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts. + */ + public native void clearInputData(); /* + IM_FONT_ATLAS->ClearInputData(); + */ + + /** + * Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory. + */ + public native void clearTexData(); /* + IM_FONT_ATLAS->ClearTexData(); + */ + + /** + * Clear output font data (glyphs storage, UV coordinates). + */ + public native void clearFonts(); /* + IM_FONT_ATLAS->ClearFonts(); + */ + + /** + * Clear all input and output. + */ + public native void clear(); /* + IM_FONT_ATLAS->Clear(); + */ + + // Build atlas, retrieve pixel data. + // User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID(). + // The pitch is always = Width * BytesPerPixels (1 or 4) + // Building in RGBA32 format is provided for convenience and compatibility, but note that unless you manually manipulate or copy color data into + // the texture (e.g. when using the AddCustomRect*** api), then the RGB pixels emitted will always be white (~75% of memory/bandwidth waste. + + /** + * Build pixels data. This is called automatically for you by the GetTexData*** functions. + */ + public native boolean build(); /* + return IM_FONT_ATLAS->Build(); + */ + + /** + * 1 byte-per-pixel + */ + public ByteBuffer getTexDataAsAlpha8(final ImInt outWidth, final ImInt outHeight) { + return getTexDataAsAlpha8(outWidth, outHeight, new ImInt()); + } + + /** + * 1 byte-per-pixel + */ + public ByteBuffer getTexDataAsAlpha8(final ImInt outWidth, final ImInt outHeight, final ImInt outBytesPerPixel) { + final byte[] tmpBuff = getTexDataAsAlpha8(outWidth.data, outHeight.data, outBytesPerPixel.data); + final ByteBuffer buffer = ByteBuffer.allocateDirect(tmpBuff.length).order(ByteOrder.nativeOrder()); + buffer.put(tmpBuff); + buffer.flip(); + return buffer; + } + + private native byte[] getTexDataAsAlpha8(int[] outWidth, int[] outHeight, int[] outBytesPerPixel); /* + unsigned char* pixels; + IM_FONT_ATLAS->GetTexDataAsAlpha8(&pixels, &outWidth[0], &outHeight[0], &outBytesPerPixel[0]); + int size = outWidth[0] * outHeight[0] * outBytesPerPixel[0]; + jbyteArray jBytes = env->NewByteArray(size); + env->SetByteArrayRegion(jBytes, 0, size, (jbyte*)pixels); + return jBytes; + */ + + /** + * 4 bytes-per-pixel + */ + public ByteBuffer getTexDataAsRGBA32(final ImInt outWidth, final ImInt outHeight) { + return getTexDataAsRGBA32(outWidth, outHeight, new ImInt()); + } + + /** + * 4 bytes-per-pixel + */ + public ByteBuffer getTexDataAsRGBA32(final ImInt outWidth, final ImInt outHeight, final ImInt outBytesPerPixel) { + final byte[] tmpBuff = nGetTexDataAsRGBA32(outWidth.data, outHeight.data, outBytesPerPixel.data); + final ByteBuffer buffer = ByteBuffer.allocateDirect(tmpBuff.length).order(ByteOrder.nativeOrder()); + buffer.put(tmpBuff); + buffer.flip(); + return buffer; + } + + private native byte[] nGetTexDataAsRGBA32(int[] outWidth, int[] outHeight, int[] outBytesPerPixel); /* + unsigned char* pixels; + IM_FONT_ATLAS->GetTexDataAsRGBA32(&pixels, &outWidth[0], &outHeight[0], &outBytesPerPixel[0]); + int size = outWidth[0] * outHeight[0] * outBytesPerPixel[0]; + jbyteArray jBytes = env->NewByteArray(size); + env->SetByteArrayRegion(jBytes, 0, size, (jbyte*)pixels); + return jBytes; + */ + + public native boolean isBuilt(); /* + return IM_FONT_ATLAS->IsBuilt(); + */ + + public native void setTexID(int imTextureId); /* + IM_FONT_ATLAS->SetTexID((ImTextureID)imTextureId); + */ + + //------------------------------------------- + // Glyph Ranges + //------------------------------------------- + + // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) + // NB: Make sure that your string are UTF-8 and NOT in your local code page. In C++11, you can create UTF-8 string literal using the u8"Hello world" syntax. See FAQ for details. + // NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data. + + /*JNI + #define RETURN_GLYPH_2_SHORT(glyphs) \ + int size = sizeof(glyphs); \ + jshortArray jShorts = env->NewShortArray(size); \ + env->SetShortArrayRegion(jShorts, 0, size, (jshort*)glyphs); \ + return jShorts; + */ + + /** + * Basic Latin, Extended Latin + */ + public native short[] getGlyphRangesDefault(); /* + RETURN_GLYPH_2_SHORT(IM_FONT_ATLAS->GetGlyphRangesDefault()); + */ + + /** + * Default + Korean characters + */ + public native short[] getGlyphRangesKorean(); /* + RETURN_GLYPH_2_SHORT(IM_FONT_ATLAS->GetGlyphRangesKorean()); + */ + + /** + * Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs + */ + public native short[] getGlyphRangesJapanese(); /* + RETURN_GLYPH_2_SHORT(IM_FONT_ATLAS->GetGlyphRangesJapanese()); + */ + + /** + * Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs + */ + public native short[] getGlyphRangesChineseFull(); /* + RETURN_GLYPH_2_SHORT(IM_FONT_ATLAS->GetGlyphRangesChineseFull()); + */ + + /** + * Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese + */ + public native short[] getGlyphRangesChineseSimplifiedCommon(); /* + RETURN_GLYPH_2_SHORT(IM_FONT_ATLAS->GetGlyphRangesChineseSimplifiedCommon()); + */ + + /** + * Default + about 400 Cyrillic characters + */ + public native short[] getGlyphRangesCyrillic(); /* + RETURN_GLYPH_2_SHORT(IM_FONT_ATLAS->GetGlyphRangesCyrillic()); + */ + + /** + * Default + Thai characters + */ + public native short[] getGlyphRangesThai(); /* + RETURN_GLYPH_2_SHORT(IM_FONT_ATLAS->GetGlyphRangesThai()); + */ + + /** + * Default + Vietnamese characters + */ + public native short[] getGlyphRangesVietnamese(); /* + RETURN_GLYPH_2_SHORT(IM_FONT_ATLAS->GetGlyphRangesVietnamese()); + */ + + //------------------------------------------- + // [BETA] Custom Rectangles/Glyphs API + //------------------------------------------- + + // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. + // After calling Build(), you can query the rectangle position and render your pixels. + // You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), + // so you can render e.g. custom colorful icons and use them as regular glyphs. + // Read docs/FONTS.txt for more details about using colorful icons. + + /** + * Id needs to be >= 0x110000. Id >= 0x80000000 are reserved for ImGui and ImDrawList + */ + public native int addCustomRectRegular(int id, int width, int height); /* + return IM_FONT_ATLAS->AddCustomRectRegular((unsigned int)id, width, height); + */ + + /** + * Id needs to be < 0x110000 to register a rectangle to map into a specific font. + */ + public int addCustomRectFontGlyph(final ImFont imFont, final short id, final int width, final int height, final float advanceX) { + return nAddCustomRectFontGlyph(imFont.ptr, id, width, height, advanceX); + } + + private native int nAddCustomRectFontGlyph(long imFontPtr, short id, int width, int height, float advanceX); /* + return IM_FONT_ATLAS->AddCustomRectFontGlyph((ImFont*)imFontPtr, id, width, height, advanceX); + */ + + /** + * Id needs to be < 0x110000 to register a rectangle to map into a specific font. + */ + public int addCustomRectFontGlyph(final ImFont imFont, final short id, final int width, final int height, final float advanceX, final float offsetX, final float offsetY) { + return nAddCustomRectFontGlyph(imFont.ptr, id, width, height, advanceX, offsetX, offsetY); + } + + private native int nAddCustomRectFontGlyph(long imFontPtr, short id, int width, int height, float advanceX, float offsetX, float offsetY); /* + return IM_FONT_ATLAS->AddCustomRectFontGlyph((ImFont*)imFontPtr, id, width, height, advanceX, ImVec2(offsetX, offsetY)); + */ + + // TODO GetCustomRectByIndex + + //------------------------------------------- + // Members + //------------------------------------------- + + /** + * Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert. + */ + public native boolean getLocked(); /* + return IM_FONT_ATLAS->Locked; + */ + + /** + * Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert. + */ + public native void setLocked(boolean locked); /* + IM_FONT_ATLAS->Locked = locked; + */ + + /** + * Build flags (see ImFontAtlasFlags_) + */ + public native int getFlags(); /* + return IM_FONT_ATLAS->Flags; + */ + + /** + * Build flags (see ImFontAtlasFlags_) + */ + public native void setFlags(int imFontAtlasFlags); /* + IM_FONT_ATLAS->Flags = imFontAtlasFlags; + */ + + /** + * User data to refer to the texture once it has been uploaded to user's graphic systems. + * It is passed back to you during rendering via the ImDrawCmd structure. + */ + public native int getTexID(); /* + return (int)(long)(void*)IM_FONT_ATLAS->TexID; + */ + + /** + * Texture width desired by user before Build(). Must be a power-of-two. + * If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. + */ + public native int getTexDesiredWidth(); /* + return IM_FONT_ATLAS->TexDesiredWidth; + */ + + /** + * Texture width desired by user before Build(). Must be a power-of-two. + * If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. + */ + public native void setTexDesiredWidth(int texDesiredWidth); /* + IM_FONT_ATLAS->TexDesiredWidth = texDesiredWidth; + */ + + /** + * Padding between glyphs within texture in pixels. Defaults to 1. + * If your rendering method doesn't rely on bilinear filtering you may set this to 0. + */ + public native int getTexGlyphPadding(); /* + return IM_FONT_ATLAS->TexGlyphPadding; + */ + + /** + * Padding between glyphs within texture in pixels. Defaults to 1. + * If your rendering method doesn't rely on bilinear filtering you may set this to 0. + */ + public native void setTexGlyphPadding(int texGlyphPadding); /* + IM_FONT_ATLAS->TexGlyphPadding = texGlyphPadding; + */ +} diff --git a/imgui-binding/src/main/java/imgui/ImFontConfig.java b/imgui-binding/src/main/java/imgui/ImFontConfig.java new file mode 100644 index 0000000..c072ec1 --- /dev/null +++ b/imgui-binding/src/main/java/imgui/ImFontConfig.java @@ -0,0 +1,321 @@ +package imgui; + +public final class ImFontConfig implements ImDestroyable { + final long ptr; + + private short[] glyphRanges; + + /** + * This class will create a native structure. + * Call {@link #destroy()} method to manually free used memory. + */ + public ImFontConfig() { + ImGui.touch(); + ptr = nCreate(); + setFontDataOwnedByAtlas(false); // Read method javadoc + } + + ImFontConfig(final long ptr) { + this.ptr = ptr; + setFontDataOwnedByAtlas(false); // Read method javadoc + } + + @Override + public void destroy() { + nDestroy(ptr); + } + + /*JNI + #include + #include "jni_common.h" + + jfieldID imFontConfigPtrID; + + #define IM_FONT_CONFIG ((ImFontConfig*)env->GetLongField(object, imFontConfigPtrID)) + */ + + static native void nInit(); /* + jclass jImFontConfigClass = env->FindClass("imgui/ImFontConfig"); + imFontConfigPtrID = env->GetFieldID(jImFontConfigClass, "ptr", "J"); + */ + + private native long nCreate(); /* + ImFontConfig* imFontConfig = new ImFontConfig(); + return (long)imFontConfig; + */ + + private native void nDestroy(long ptr); /* + delete (ImFontConfig*)ptr; + */ + + /** + * TTF/OTF data + */ + public native byte[] getFontData(); /* + int size = IM_FONT_CONFIG->FontDataSize; + jbyteArray jBytes = env->NewByteArray(size); + env->SetByteArrayRegion(jBytes, 0, size, (jbyte*)IM_FONT_CONFIG->FontData); + return jBytes; + */ + + /** + * TTF/OTF data + */ + public native void setFontData(byte[] fontData); /* + IM_FONT_CONFIG->FontData = &fontData[0]; + */ + + /** + * TTF/OTF data size + */ + public native int getFontDataSize(); /* + return IM_FONT_CONFIG->FontDataSize; + */ + + /** + * TTF/OTF data size + */ + public native void setFontDataSize(int fontDataSize); /* + IM_FONT_CONFIG->FontDataSize = fontDataSize; + */ + + /** + * TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). + */ + public native boolean getFontDataOwnedByAtlas(); /* + return IM_FONT_CONFIG->FontDataOwnedByAtlas; + */ + + /** + * TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). + *

+ * BINDING NOTICE: By default binding will set this value to false. + * If this is not done, Dear ImGui will try to free memory allocated by JVM to store fonts data while running {@link ImGui#destroyContext()}. + * This will result into a native exception, since JVM by itself controls it's own resources. + */ + public native void setFontDataOwnedByAtlas(boolean isFontDataOwnedByAtlas); /* + IM_FONT_CONFIG->FontDataOwnedByAtlas = isFontDataOwnedByAtlas; + */ + + /** + * Index of font within TTF/OTF file + */ + public native int getFontNo(); /* + return IM_FONT_CONFIG->FontNo; + */ + + /** + * Index of font within TTF/OTF file + */ + public native void setFontNo(int fontNo); /* + IM_FONT_CONFIG->FontNo = fontNo; + */ + + /** + * Size in pixels for rasterizer (more or less maps to the resulting font height). + */ + public native float getSizePixels(); /* + return IM_FONT_CONFIG->SizePixels; + */ + + /** + * Size in pixels for rasterizer (more or less maps to the resulting font height). + */ + public native void setSizePixels(float sizePixels); /* + IM_FONT_CONFIG->SizePixels = sizePixels; + */ + + /** + * Rasterize at higher quality for sub-pixel positioning. + * Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details. + */ + public native int getOversampleH(); /* + return IM_FONT_CONFIG->OversampleH; + */ + + /** + * Rasterize at higher quality for sub-pixel positioning. + * Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details. + */ + public native void setOversampleH(int oversampleH); /* + IM_FONT_CONFIG->OversampleH = oversampleH; + */ + + /** + * Rasterize at higher quality for sub-pixel positioning. + * We don't use sub-pixel positions on the Y axis. + */ + public native int getOversampleV(); /* + return IM_FONT_CONFIG->OversampleV; + */ + + /** + * Rasterize at higher quality for sub-pixel positioning. + * We don't use sub-pixel positions on the Y axis. + */ + public native void setOversampleV(int oversampleV); /* + IM_FONT_CONFIG->OversampleV = oversampleV; + */ + + /** + * Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. + * If enabled, you can set OversampleH/V to 1. + */ + public native boolean getPixelSnapH(); /* + return IM_FONT_CONFIG->PixelSnapH; + */ + + /** + * Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. + * If enabled, you can set OversampleH/V to 1. + */ + public native void setPixelSnapH(boolean isPixelSnapH); /* + IM_FONT_CONFIG->PixelSnapH = isPixelSnapH; + */ + + /** + * Extra spacing (in pixels) between glyphs. Only X axis is supported for now. + */ + public native void getGlyphExtraSpacing(ImVec2 dstImVec2); /* + Jni::ImVec2Cpy(env, &IM_FONT_CONFIG->GlyphExtraSpacing, dstImVec2); + */ + + /** + * Extra spacing (in pixels) between glyphs. Only X axis is supported for now. + */ + public native void setGlyphExtraSpacing(float x, float y); /* + IM_FONT_CONFIG->GlyphExtraSpacing.x = x; + IM_FONT_CONFIG->GlyphExtraSpacing.y = y; + */ + + /** + * Offset all glyphs from this font input. + */ + public native void getGlyphOffset(ImVec2 dstImVec2); /* + Jni::ImVec2Cpy(env, &IM_FONT_CONFIG->GlyphOffset, dstImVec2); + */ + + /** + * Offset all glyphs from this font input. + */ + public native void setGlyphOffset(float x, float y); /* + IM_FONT_CONFIG->GlyphOffset.x = x; + IM_FONT_CONFIG->GlyphOffset.y = y; + */ + + /** + * Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). + * THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. + */ + public short[] getGlyphRanges() { + return glyphRanges; + } + + /** + * Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). + * THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. + */ + public void setGlyphRanges(final short[] glyphRanges) { + this.glyphRanges = glyphRanges; + nSetGlyphRanges(glyphRanges); + } + + private native void nSetGlyphRanges(short[] glyphRanges); /* + IM_FONT_CONFIG->GlyphRanges = glyphRanges != NULL ? (ImWchar*)&glyphRanges[0] : NULL; + */ + + /** + * Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font + */ + public native float getGlyphMinAdvanceX(); /* + return IM_FONT_CONFIG->GlyphMinAdvanceX; + */ + + /** + * Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font + */ + public native void setGlyphMinAdvanceX(float glyphMinAdvanceX); /* + IM_FONT_CONFIG->GlyphMinAdvanceX = glyphMinAdvanceX; + */ + + /** + * Maximum AdvanceX for glyphs + */ + public native float getGlyphMaxAdvanceX(); /* + return IM_FONT_CONFIG->GlyphMaxAdvanceX; + */ + + /** + * Maximum AdvanceX for glyphs + */ + public native void setGlyphMaxAdvanceX(float glyphMaxAdvanceX); /* + IM_FONT_CONFIG->GlyphMaxAdvanceX = glyphMaxAdvanceX; + */ + + /** + * Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). + * You may want to use GlyphOffset.y when merge font of different heights. + */ + public native boolean getMergeMode(); /* + return IM_FONT_CONFIG->MergeMode; + */ + + /** + * Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). + * You may want to use GlyphOffset.y when merge font of different heights. + */ + public native void setMergeMode(boolean mergeMode); /* + IM_FONT_CONFIG->MergeMode = mergeMode; + */ + + /** + * Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. + */ + public native int getRasterizerFlags(); /* + return IM_FONT_CONFIG->RasterizerFlags; + */ + + /** + * Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. + */ + public native void setRasterizerFlags(int rasterizerFlags); /* + IM_FONT_CONFIG->RasterizerFlags = (unsigned int)rasterizerFlags; + */ + + /** + * Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. + */ + public native float getRasterizerMultiply(); /* + return IM_FONT_CONFIG->RasterizerMultiply; + */ + + /** + * Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. + */ + public native void setRasterizerMultiply(float rasterizerMultiply); /* + IM_FONT_CONFIG->RasterizerMultiply = rasterizerMultiply; + */ + + /** + * Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. + */ + public native short getEllipsisChar(); /* + return (short)IM_FONT_CONFIG->EllipsisChar; + */ + + /** + * Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. + */ + public native void setEllipsisChar(short ellipsisChar); /* + IM_FONT_CONFIG->EllipsisChar = (ImWchar)ellipsisChar; + */ + + // [Internal] + + /** + * Name (strictly to ease debugging) + */ + public native void setName(String name); /* + strcpy(IM_FONT_CONFIG->Name, name); + */ +} diff --git a/imgui-binding/src/main/java/imgui/ImFontGlyph.java b/imgui-binding/src/main/java/imgui/ImFontGlyph.java new file mode 100644 index 0000000..6d620f0 --- /dev/null +++ b/imgui-binding/src/main/java/imgui/ImFontGlyph.java @@ -0,0 +1,186 @@ +package imgui; + +public final class ImFontGlyph implements ImDestroyable { + final long ptr; + + /** + * This class will create a native structure. + * Call {@link #destroy()} method to manually free used memory. + */ + public ImFontGlyph() { + ImGui.touch(); + ptr = nCreate(); + } + + ImFontGlyph(final long ptr) { + this.ptr = ptr; + } + + @Override + public void destroy() { + nDestroy(ptr); + } + + /*JNI + #include + #include "jni_common.h" + + jfieldID imFontGlyphPtrID; + + #define IM_FONT_GLYPH ((ImFontGlyph*)env->GetLongField(object, imFontGlyphPtrID)) + */ + + static native void nInit(); /* + jclass jImFontGlyphClass = env->FindClass("imgui/ImFontGlyph"); + imFontGlyphPtrID = env->GetFieldID(jImFontGlyphClass, "ptr", "J"); + */ + + private native long nCreate(); /* + ImFontConfig* imFontConfig = new ImFontConfig(); + return (long)imFontConfig; + */ + + private native void nDestroy(long ptr); /* + delete (ImFontConfig*)ptr; + */ + + /** + * 0x0000..0xFFFF + */ + public native short getCodepoint(); /* + return (short)IM_FONT_GLYPH->Codepoint; + */ + + /** + * 0x0000..0xFFFF + */ + public native void setCodepoint(short codepoint); /* + IM_FONT_GLYPH->Codepoint = (ImWchar)codepoint; + */ + + /** + * Distance to next character (= data from font + ImFontConfig::GlyphExtraSpacing.x baked in) + */ + public native float getAdvanceX(); /* + return IM_FONT_GLYPH->AdvanceX; + */ + + /** + * Distance to next character (= data from font + ImFontConfig::GlyphExtraSpacing.x baked in) + */ + public native void setAdvanceX(float advanceX); /* + IM_FONT_GLYPH->AdvanceX = advanceX; + */ + + /** + * Glyph corners + */ + public native float getX0(); /* + return IM_FONT_GLYPH->X0; + */ + + /** + * Glyph corners + */ + public native void setX0(float x0); /* + IM_FONT_GLYPH->X0 = x0; + */ + + /** + * Glyph corners + */ + public native float getY0(); /* + return IM_FONT_GLYPH->Y0; + */ + + /** + * Glyph corners + */ + public native void setY0(float y0); /* + IM_FONT_GLYPH->Y0 = y0; + */ + + /** + * Glyph corners + */ + public native float getX1(); /* + return IM_FONT_GLYPH->X1; + */ + + /** + * Glyph corners + */ + public native void setX1(float x1); /* + IM_FONT_GLYPH->X1 = x1; + */ + + /** + * Glyph corners + */ + public native float getY1(); /* + return IM_FONT_GLYPH->Y1; + */ + + /** + * Glyph corners + */ + public native void setY1(float y1); /* + IM_FONT_GLYPH->Y1 = y1; + */ + + /** + * Texture coordinates + */ + public native float getU0(); /* + return IM_FONT_GLYPH->U0; + */ + + /** + * Texture coordinates + */ + public native void setU0(float u0); /* + IM_FONT_GLYPH->U0 = u0; + */ + + /** + * Texture coordinates + */ + public native float getV0(); /* + return IM_FONT_GLYPH->V0; + */ + + /** + * Texture coordinates + */ + public native void setV0(float v0); /* + IM_FONT_GLYPH->V0 = v0; + */ + + /** + * Texture coordinates + */ + public native float getU1(); /* + return IM_FONT_GLYPH->U1; + */ + + /** + * Texture coordinates + */ + public native void setU1(float u1); /* + IM_FONT_GLYPH->U1 = u1; + */ + + /** + * Texture coordinates + */ + public native float getV1(); /* + return IM_FONT_GLYPH->V1; + */ + + /** + * Texture coordinates + */ + public native void setV1(float v1); /* + IM_FONT_GLYPH->V1 = v1; + */ +} diff --git a/imgui-binding/src/main/java/imgui/ImGui.java b/imgui-binding/src/main/java/imgui/ImGui.java index 276ab6d..3c6c7cc 100644 --- a/imgui-binding/src/main/java/imgui/ImGui.java +++ b/imgui-binding/src/main/java/imgui/ImGui.java @@ -17,14 +17,16 @@ public final class ImGui { private static final String LIB_NAME_DEFAULT = System.getProperty("os.arch").contains("64") ? "imgui-java64" : "imgui-java"; private static final String LIB_TMP_DIR_PREFIX = "imgui-java-bin_" + System.getProperty("user.name", "user"); - private static final ImDrawData DRAW_DATA = new ImDrawData(100_000, 100_000, 1000); - private static final ImGuiIO IMGUI_IO = new ImGuiIO(); - private static final ImGuiStyle IMGUI_STYLE = new ImGuiStyle(); + private static final ImDrawData DRAW_DATA; + private static final ImGuiIO IMGUI_IO; + private static final ImGuiStyle IMGUI_STYLE; private static final ImDrawList IM_DRAW_LIST_WINDOW = new ImDrawList(ImDrawList.TYPE_WINDOW); private static final ImDrawList IM_DRAW_LIST_BACKGROUND = new ImDrawList(ImDrawList.TYPE_BACKGROUND); private static final ImDrawList IM_DRAW_LIST_FOREGROUND = new ImDrawList(ImDrawList.TYPE_FOREGROUND); + private static ImFont font; + static { final String libPath = System.getProperty(LIB_PATH_PROP); final String libName = System.getProperty(LIB_NAME_PROP, LIB_NAME_DEFAULT); @@ -40,9 +42,17 @@ public final class ImGui { System.loadLibrary(libName); } + DRAW_DATA = new ImDrawData(100_000, 100_000, 1000); + IMGUI_IO = new ImGuiIO(); + IMGUI_STYLE = new ImGuiStyle(); + nInitJni(); ImDrawList.nInit(); ImDrawData.nInit(); + ImFontAtlas.nInit(); + ImFontConfig.nInit(); + ImFontGlyph.nInit(); + ImFont.nInit(); nInitInputTextData(); } @@ -81,6 +91,14 @@ public final class ImGui { } } + /** + * For internal usage. + * Method is used to initiate static instantiation (loading of the native libraries etc.). + * Otherwise native libraries will be loaded on demand and natively mapped objects won't work. + */ + static void touch() { + } + private ImGui() { } @@ -107,7 +125,13 @@ public final class ImGui { ImGui::CreateContext(); */ - // public static void CreateContext(ImFontAtlas sharedFontAtlas) TODO create context with fonts + public static void createContext(ImFontAtlas sharedFontAtlas) { + nCreateContext(sharedFontAtlas.ptr); + } + + private static native void nCreateContext(long sharedFontAtlasPtr); /* + ImGui::CreateContext((ImFontAtlas*)sharedFontAtlasPtr); + */ public static native void destroyContext(); /* ImGui::DestroyContext(); @@ -769,7 +793,13 @@ public final class ImGui { // Parameters stacks (shared) - // TODO void PushFont(ImFont* font); + public static void pushFont(ImFont font) { + nPushFont(font.ptr); + } + + private static native void nPushFont(long fontPtr); /* + ImGui::PushFont((ImFont*)fontPtr); + */ public static native void popFont(); /* ImGui::PopFont(); @@ -815,7 +845,19 @@ public final class ImGui { Jni::ImVec4Cpy(env, ImGui::GetStyleColorVec4(imGuiStyleVar), dstImVec4); */ - // TODO ImFont* GetFont(); + /** + * Get current font. + */ + public static ImFont getFont() { + if (font == null) { + font = new ImFont(nGetFont()); + } + return font; + } + + private static native long nGetFont(); /* + return (long)ImGui::GetFont(); + */ /** * Get current font size (= height in pixels) of current font with current scale applied @@ -854,6 +896,7 @@ public final class ImGui { /** * Retrieve given color with style alpha applied + *

* BINDING NOTICE: Since {@link #getColorU32(int)} has the same signature, this specific method has an 'i' suffix. */ public static native int getColorU32i(int col); /* @@ -1196,6 +1239,7 @@ public final class ImGui { /** * Formatted text + *

* BINDING NOTICE: Since all text formatting could be done on Java side, this call is equal to {@link ImGui#textUnformatted(String)}. */ public static native void text(String text); /* @@ -3349,7 +3393,6 @@ public final class ImGui { */ // Widgets: List Boxes - // - FIXME: To be consistent with all the newer API, ListBoxHeader/ListBoxFooter should in reality be called BeginListBox/EndListBox. Will rename them. public static void listBox(String label, ImInt currentItem, String[] items, int itemsCount) { nListBox(label, currentItem.data, items, itemsCount, -1); diff --git a/imgui-binding/src/main/java/imgui/ImGuiIO.java b/imgui-binding/src/main/java/imgui/ImGuiIO.java index a4746fa..256b0a4 100644 --- a/imgui-binding/src/main/java/imgui/ImGuiIO.java +++ b/imgui-binding/src/main/java/imgui/ImGuiIO.java @@ -8,6 +8,8 @@ import imgui.callbacks.ImStrSupplier; * Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage. */ public final class ImGuiIO { + private ImFontAtlas imFontAtlas; + ImGuiIO() { } @@ -152,11 +154,70 @@ public final class ImGuiIO { ImGui::GetIO().KeyRepeatRate = keyRepeatRate; */ - // TODO fonts configuration + /** + * Font atlas: load, rasterize and pack one or more fonts into a single texture. + */ + public ImFontAtlas getFonts() { + // on demand instantiation + // will throw native exception if Dear ImGui context isn't created (like in the original library) + if (imFontAtlas == null) { + imFontAtlas = new ImFontAtlas(nGetFontsPtr()); + } + return imFontAtlas; + } - // BINDING NOTICE: this is a stub to pass important for ImGui info - public native void setFontsTexID(int id); /* - ImGui::GetIO().Fonts->TexID = (ImTextureID)id; + private native long nGetFontsPtr(); /* + return (long)ImGui::GetIO().Fonts; + */ + + /** + * Font atlas: load, rasterize and pack one or more fonts into a single texture. + *

+ * BINDING NOTICE: You SHOULD manually destroy previously used ImFontAtlas. + */ + public void setFonts(final ImFontAtlas imFontAtlas) { + this.imFontAtlas = imFontAtlas; + nSetFonts(imFontAtlas.ptr); + } + + private native void nSetFonts(long imFontAtlasPtr); /* + ImGui::GetIO().Fonts = (ImFontAtlas*)imFontAtlasPtr; + */ + + /** + * Global scale all fonts + */ + public native float getFontGlobalScale(); /* + return ImGui::GetIO().FontGlobalScale; + */ + + /** + * Global scale all fonts + */ + public native void setFontGlobalScale(float fontGlobalScale); /* + ImGui::GetIO().FontGlobalScale = fontGlobalScale; + */ + + /** + * Allow user scaling text of individual window with CTRL+Wheel. + */ + public native boolean getFontAllowUserScaling(); /* + return ImGui::GetIO().FontAllowUserScaling; + */ + + /** + * Allow user scaling text of individual window with CTRL+Wheel. + */ + public native void setFontAllowUserScaling(boolean fontAllowUserScaling); /* + ImGui::GetIO().FontAllowUserScaling = fontAllowUserScaling; + */ + + public void setFontDefault(final ImFont fontDefault) { + nSetFontDefault(fontDefault.ptr); + } + + private native void nSetFontDefault(long fontDefaultPtr); /* + ImGui::GetIO().FontDefault = (ImFont*)fontDefaultPtr; */ // Miscellaneous options @@ -626,8 +687,7 @@ public final class ImGuiIO { * Queue new character input. */ public native void addInputCharacter(int c); /* - if (c > 0 && c < 0x10000) - ImGui::GetIO().AddInputCharacter((unsigned short)c); + ImGui::GetIO().AddInputCharacter((unsigned int)c); */ /** diff --git a/imgui-binding/src/main/java/imgui/ImGuiStyle.java b/imgui-binding/src/main/java/imgui/ImGuiStyle.java index b287268..43bea1f 100644 --- a/imgui-binding/src/main/java/imgui/ImGuiStyle.java +++ b/imgui-binding/src/main/java/imgui/ImGuiStyle.java @@ -440,4 +440,8 @@ public final class ImGuiStyle { env->DeleteLocalRef(jColors); } */ + + public native void scaleAllSizes(float scaleFactor); /* + ImGui::GetStyle().ScaleAllSizes(scaleFactor); + */ } diff --git a/imgui-binding/src/main/java/imgui/TexDataRGBA32.java b/imgui-binding/src/main/java/imgui/TexDataRGBA32.java deleted file mode 100644 index 1ac57a4..0000000 --- a/imgui-binding/src/main/java/imgui/TexDataRGBA32.java +++ /dev/null @@ -1,48 +0,0 @@ -package imgui; - -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -public final class TexDataRGBA32 { - public int width; - public int height; - - public ByteBuffer pixelBuffer; - - private TexDataRGBA32() { - final int pixelMax = 131072; - pixelBuffer = ByteBuffer.allocateDirect(pixelMax).order(ByteOrder.nativeOrder()); - } - - public static TexDataRGBA32 create() { - final TexDataRGBA32 data = new TexDataRGBA32(); - data.nFillData(data.pixelBuffer); - return data; - } - - /*JNI - #include - */ - - private native void nFillData(Buffer pixelBuf); /* - jclass jTexDataClass = env->GetObjectClass(object); - - if(jTexDataClass == NULL) - return; - - jfieldID widthID = env->GetFieldID(jTexDataClass, "width", "I"); - jfieldID heightID = env->GetFieldID(jTexDataClass, "height", "I"); - - unsigned char* pixels; - int width, height; - - ImGuiIO& io = ImGui::GetIO(); - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - - env->SetIntField(object, widthID, width); - env->SetIntField(object, heightID, height); - - memcpy(pixelBuf, pixels, width * height * 4); - */ -} diff --git a/imgui-lwjgl3/src/main/java/imgui/gl3/ImGuiImplGl3.java b/imgui-lwjgl3/src/main/java/imgui/gl3/ImGuiImplGl3.java index 71434a8..eeed6f1 100644 --- a/imgui-lwjgl3/src/main/java/imgui/gl3/ImGuiImplGl3.java +++ b/imgui-lwjgl3/src/main/java/imgui/gl3/ImGuiImplGl3.java @@ -1,14 +1,16 @@ package imgui.gl3; import imgui.ImDrawData; +import imgui.ImFontAtlas; import imgui.ImGui; -import imgui.TexDataRGBA32; +import imgui.ImInt; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UncheckedIOException; +import java.nio.ByteBuffer; import java.util.Objects; import static org.lwjgl.opengl.GL30.*; @@ -191,18 +193,21 @@ public final class ImGuiImplGl3 { } private void prepareFont() { - final TexDataRGBA32 texData = TexDataRGBA32.create(); - gFontTexture = glGenTextures(); + final ImFontAtlas fontAtlas = ImGui.getIO().getFonts(); + final ImInt width = new ImInt(); + final ImInt height = new ImInt(); + final ByteBuffer buffer = fontAtlas.getTexDataAsRGBA32(width, height); + glBindTexture(GL_TEXTURE_2D, gFontTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texData.width, texData.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.pixelBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width.get(), height.get(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - ImGui.getIO().setFontsTexID(gFontTexture); + fontAtlas.setTexID(gFontTexture); } private void backupGlState() { diff --git a/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java b/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java index 5cd85ff..f50742d 100644 --- a/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java +++ b/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java @@ -1,4 +1,6 @@ import imgui.ImBool; +import imgui.ImFontAtlas; +import imgui.ImFontConfig; import imgui.ImGui; import imgui.ImGuiIO; import imgui.ImString; @@ -11,13 +13,16 @@ import imgui.enums.ImGuiConfigFlags; import imgui.enums.ImGuiInputTextFlags; import imgui.enums.ImGuiKey; import imgui.enums.ImGuiMouseCursor; -import imgui.enums.ImGuiWindowFlags; import imgui.gl3.ImGuiImplGl3; import org.lwjgl.glfw.GLFWErrorCallback; import org.lwjgl.glfw.GLFWVidMode; import org.lwjgl.opengl.GL; import org.lwjgl.system.MemoryStack; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; import java.nio.IntBuffer; import java.util.Objects; @@ -47,16 +52,16 @@ public final class ImGuiGlfwExample { // Mouse cursors provided by GLFW private final long[] mouseCursors = new long[ImGuiMouseCursor.COUNT]; + // LWJGL3 rendered itself (SHOULD be initialized) private final ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3(); - // Local app variables go here - private final String imguiDemoLink = "https://raw.githubusercontent.com/ocornut/imgui/v1.74/imgui_demo.cpp"; - private final byte[] testPayload = "Test Payload".getBytes(); + // Local variables for application goes here + private final String imguiDemoLink = "https://raw.githubusercontent.com/ocornut/imgui/v1.74/imgui_demo.cpp"; // Link to put into clipboard + private final byte[] testPayload = "Test Payload".getBytes(); // Test data for payload. Should be represented as raw byt array. private String dropTargetText = "Drop Here"; - private float[] backgroundColor = new float[]{0.5f, 0, 0}; + private float[] backgroundColor = new float[]{0.5f, 0, 0}; // To modify background color dynamically private int clickCount = 0; private final ImString resizableStr = new ImString(5); - private final ImBool showDemoWindow = new ImBool(); public void run() { @@ -67,7 +72,7 @@ public final class ImGuiGlfwExample { destroyGlfw(); } - // Method initializes GLFW window. All code is mostly a copy-paste from the official LWJGL3 website. + // Method initializes GLFW window. All code is mostly a copy-paste from the official LWJGL3 "Get Started": https://www.lwjgl.org/guide private void initGlfw() { // Setup an error callback. The default implementation // will print the error message in System.err. @@ -85,7 +90,7 @@ public final class ImGuiGlfwExample { glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE); // the window will be maximized // Create the window - window = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, "ImGui+GLFW+LWJGL Example", NULL, NULL); + window = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, "Dear ImGui + GLFW + LWJGL Example", NULL, NULL); if (window == NULL) { throw new RuntimeException("Failed to create the GLFW window"); @@ -122,22 +127,21 @@ public final class ImGuiGlfwExample { // Here we will initialize ImGui stuff. private void initImGui() { // IMPORTANT!! - // This line is critical for ImGui to work. + // This line is critical for Dear ImGui to work. ImGui.createContext(); - // ImGui provides three different color schemas for styling. We will use the classic one here. + // ImGui provides 3 different color schemas for styling. We will use the classic one here. + // Try others with ImGui.styleColors*() methods. ImGui.styleColorsClassic(); - // ImGui.StyleColorsDark(); // This is a default style for ImGui - // ImGui.StyleColorsLight(); // Initialize ImGuiIO config final ImGuiIO io = ImGui.getIO(); - io.setIniFilename(null); - io.setConfigFlags(ImGuiConfigFlags.NavEnableKeyboard); - io.setBackendFlags(ImGuiBackendFlags.HasMouseCursors); - io.setBackendPlatformName("imgui_java_impl_glfw"); - io.setBackendRendererName("imgui_java_impl_lwjgl"); + io.setIniFilename(null); // We don't want to save .ini file + io.setConfigFlags(ImGuiConfigFlags.NavEnableKeyboard); // Navigation with keyboard + io.setBackendFlags(ImGuiBackendFlags.HasMouseCursors); // Mouse cursors to display while resizing windows etc. + io.setBackendPlatformName("imgui_java_impl_glfw"); // For debug purpose + io.setBackendRendererName("imgui_java_impl_lwjgl"); // For debug purpose // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array. final int[] keyMap = new int[ImGuiKey.COUNT]; @@ -175,7 +179,9 @@ public final class ImGuiGlfwExample { mouseCursors[ImGuiMouseCursor.ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); mouseCursors[ImGuiMouseCursor.Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); - // Here goes GLFW callbacks to update user input stuff in ImGui + // ------------------------------------------------------------ + // Here goes GLFW callbacks to update user input in Dear ImGui + glfwSetKeyCallback(window, (w, key, scancode, action, mods) -> { if (action == GLFW_PRESS) { io.setKeysDown(key, true); @@ -230,10 +236,41 @@ public final class ImGuiGlfwExample { } }); - // Initialize renderer itself + // ------------------------------------------------------------ + // Fonts configuration + + final ImFontAtlas fontAtlas = io.getFonts(); + + // Dear ImGui uses 'ProggyClean.ttf, 13px' by default + fontAtlas.addFontDefault(); + + final ImFontConfig fontConfig = new ImFontConfig(); // Keep in mind that creation of the ImFontConfig will allocate native memory + fontConfig.setRasterizerMultiply(1.2f); // This will make fonts a bit more readable + fontConfig.setGlyphRanges(fontAtlas.getGlyphRangesCyrillic()); // Additional glyphs could be added like here or in addFontFrom*() methods + + // We can add new fonts directly from file + fontAtlas.addFontFromFileTTF("imgui-lwjgl3/src/test/resources/DroidSans.ttf", 13, fontConfig); + fontAtlas.addFontFromFileTTF("imgui-lwjgl3/src/test/resources/DroidSans.ttf", 14, fontConfig); + fontAtlas.addFontFromFileTTF("imgui-lwjgl3/src/test/resources/JetBrainsMono-Regular.ttf", 13, fontConfig); + fontAtlas.addFontFromFileTTF("imgui-lwjgl3/src/test/resources/JetBrainsMono-Regular.ttf", 14, fontConfig); + + // Or directly from memory + fontConfig.setName("Roboto-Regular.ttf, 13px"); // This name will be displayed in Style Editor + fontAtlas.addFontFromMemoryTTF(loadFromResources("Roboto-Regular.ttf"), 13, fontConfig); + fontConfig.setName("Roboto-Regular.ttf, 14px"); // We can apply a new config value every time we add a new font + fontAtlas.addFontFromMemoryTTF(loadFromResources("Roboto-Regular.ttf"), 14, fontConfig); + + // After fonts were added and since we won't use fontConfig again - we should clean it + fontConfig.destroy(); + + // IMPORTANT!!! + // Method initializes renderer itself. + // This method SHOULD be called after you've initialized your ImGui configuration (fonts and so on). + // ImGui context should be created as well. imGuiGl3.init(); } + // Main application loop private void loop() { double time = 0; // to track our frame delta value @@ -244,8 +281,9 @@ public final class ImGuiGlfwExample { final double deltaTime = (time > 0) ? (currentTime - time) : 1f / 60f; time = currentTime; - // Set the clear color + // Set the clear color and do clear itself glClearColor(backgroundColor[0], backgroundColor[1], backgroundColor[2], 0.0f); + glClear(GL_COLOR_BUFFER_BIT); // Get window size properties and mouse position glfwGetWindowSize(window, winWidth, winHeight); @@ -265,16 +303,13 @@ public final class ImGuiGlfwExample { glfwSetCursor(window, mouseCursors[imguiCursor]); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); - // Clear the framebuffer - glClear(GL_COLOR_BUFFER_BIT); - // IMPORTANT!! - // Any ImGui code SHOULD go between NewFrame()/Render() methods + // Any Dear ImGui code SHOULD go between NewFrame()/Render() methods ImGui.newFrame(); - showUi(); // ImGui calls goes here + showUi(); ImGui.render(); - // After ImGui#render call we provide draw data into LWJGL3 render. + // After ImGui#render call we provide draw data into LWJGL3 renderer. // At that moment ImGui will be rendered to the current OpenGL context. imGuiGl3.render(ImGui.getDrawData()); @@ -289,9 +324,14 @@ public final class ImGuiGlfwExample { ImGui.setNextWindowSize(600, 300, ImGuiCond.Once); ImGui.setNextWindowPos(10, 10, ImGuiCond.Once); - ImGui.begin("Custom window", ImGuiWindowFlags.NoDecoration); // Start Custom window - ImGui.text("Hello from Java!"); + ImGui.begin("Custom window"); // Start Custom window + // Simple text label + ImGui.checkbox("Show demo window", showDemoWindow); + + ImGui.separator(); + + // Drag'n'Drop functionality ImGui.button("Drag me"); if (ImGui.beginDragDropSource()) { ImGui.setDragDropPayload("payload_type", testPayload, testPayload.length); @@ -308,11 +348,13 @@ public final class ImGuiGlfwExample { ImGui.endDragDropTarget(); } + // Color picker ImGui.alignTextToFramePadding(); ImGui.text("Background color:"); ImGui.sameLine(); ImGui.colorEdit3("##click_counter_col", backgroundColor, ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.NoDragDrop); + // Simple click counter if (ImGui.button("Click")) { clickCount++; } @@ -321,14 +363,24 @@ public final class ImGuiGlfwExample { } ImGui.sameLine(); ImGui.text("Count: " + clickCount); - ImGui.checkbox("Show demo window", showDemoWindow); - ImGui.newLine(); - - ImGui.inputText("Resizable input", resizableStr, ImGuiInputTextFlags.CallbackResize); - ImGui.text(String.format("text len: %d | buffer size: %d", resizableStr.getLength(), resizableStr.getBufferSize())); - ImGui.newLine(); ImGui.separator(); + + // Input field with auto-resize ability + ImGui.text("You can use text inputs with auto-resizable strings!"); + ImGui.inputText("Resizable input", resizableStr, ImGuiInputTextFlags.CallbackResize); + ImGui.text("text len:"); + ImGui.sameLine(); + ImGui.textColored(.12f, .6f, 1, 1, Integer.toString(resizableStr.getLength())); + ImGui.sameLine(); + ImGui.text("| buffer size:"); + ImGui.sameLine(); + ImGui.textColored(1, .6f, 0, 1, Integer.toString(resizableStr.getBufferSize())); + + ImGui.separator(); + ImGui.newLine(); + + // Link to the original demo file ImGui.text("Consider to look the original ImGui demo: "); ImGui.setNextItemWidth(500); ImGui.textColored(0, .8f, 0, 1, imguiDemoLink); @@ -361,6 +413,23 @@ public final class ImGuiGlfwExample { Objects.requireNonNull(glfwSetErrorCallback(null)).free(); } + private byte[] loadFromResources(final String fileName) { + try (InputStream is = Objects.requireNonNull(ImGuiGlfwExample.class.getClassLoader().getResourceAsStream(fileName)); + ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { + + final byte[] data = new byte[16384]; + + int nRead; + while ((nRead = is.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + + return buffer.toByteArray(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public static void main(final String[] args) { new ImGuiGlfwExample().run(); } diff --git a/imgui-lwjgl3/src/test/resources/DroidSans.ttf b/imgui-lwjgl3/src/test/resources/DroidSans.ttf new file mode 100644 index 0000000..767c63a Binary files /dev/null and b/imgui-lwjgl3/src/test/resources/DroidSans.ttf differ diff --git a/imgui-lwjgl3/src/test/resources/JetBrainsMono-Regular.ttf b/imgui-lwjgl3/src/test/resources/JetBrainsMono-Regular.ttf new file mode 100644 index 0000000..91d4943 Binary files /dev/null and b/imgui-lwjgl3/src/test/resources/JetBrainsMono-Regular.ttf differ diff --git a/imgui-lwjgl3/src/test/resources/Roboto-Regular.ttf b/imgui-lwjgl3/src/test/resources/Roboto-Regular.ttf new file mode 100644 index 0000000..7d9a6c4 Binary files /dev/null and b/imgui-lwjgl3/src/test/resources/Roboto-Regular.ttf differ