|
1 | 1 | package imgui;
|
2 | 2 |
|
3 |
| -import java.nio.Buffer; |
4 | 3 | import java.nio.ByteBuffer;
|
5 | 4 | import java.nio.ByteOrder;
|
6 | 5 |
|
7 | 6 | /**
|
8 |
| - * All draw data to render a Dear ImGui frame. |
| 7 | + * All draw data to render Dear ImGui frame |
| 8 | + * (NB: the style and the naming convention here is a little inconsistent, we currently preserve them for backward compatibility purpose, |
| 9 | + * as this is one of the oldest structure exposed by the library! Basically, ImDrawList == CmdList) |
9 | 10 | * <p>
|
10 |
| - * BINDING NOTICE: DO NOT TRY TO MODIFY FIELDS OF THIS CLASS MANUALLY! You should only access their values after {@link ImGui#render()} call. |
| 11 | + * BINDING NOTICE: Since it's impossible to do a 1:1 mapping with JNI, current class provides "getCmdList*()" methods. |
| 12 | + * Those are used to get the data needed to do a rendering. |
11 | 13 | */
|
12 |
| -public final class ImDrawData { |
13 |
| - public static final int V_BUFFER_SIZE = (4 + 1) * 4; |
14 |
| - public static final int I_BUFFER_SIZE = 2; |
15 |
| - public static final int CMD_BUFFER_SIZE = (1 + 4 + 1) * 4; |
16 |
| - |
17 |
| - public ByteBuffer vByteBuffer; |
18 |
| - public ByteBuffer iByteBuffer; |
19 |
| - public ByteBuffer cmdByteBuffer; |
20 |
| - |
21 |
| - public int totalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size |
22 |
| - public int totalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size |
23 |
| - public int cmdListsCount; // Number of ImDrawList* to render |
24 |
| - |
25 |
| - // Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use) |
26 |
| - // |
27 |
| - public float displayPosX; |
28 |
| - public float displayPosY; |
29 |
| - |
30 |
| - // Size of the viewport to render (== io.DisplaySize for the main viewport) |
31 |
| - // (DisplayPos+DisplaySize == lower-right of the orthogonal projection matrix to use) |
32 |
| - // |
33 |
| - public float displaySizeX; |
34 |
| - public float displaySizeY; |
35 |
| - |
36 |
| - // Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display. |
37 |
| - // |
38 |
| - public float framebufferScaleX; |
39 |
| - public float framebufferScaleY; |
40 |
| - |
41 |
| - ImDrawData(final int maxVertices, final int maxIndices, final int maxCmd) { |
42 |
| - vByteBuffer = ByteBuffer.allocateDirect(maxVertices * V_BUFFER_SIZE).order(ByteOrder.nativeOrder()); |
43 |
| - iByteBuffer = ByteBuffer.allocateDirect(maxIndices * I_BUFFER_SIZE).order(ByteOrder.nativeOrder()); |
44 |
| - cmdByteBuffer = ByteBuffer.allocateDirect(maxCmd * CMD_BUFFER_SIZE).order(ByteOrder.nativeOrder()); |
| 14 | +public final class ImDrawData implements ImDestroyable { |
| 15 | + public static final int SIZEOF_IM_DRAW_IDX = 2; |
| 16 | + public static final int SIZEOF_IM_DRAW_VERT = (4 + 1) * 4; |
| 17 | + |
| 18 | + private static final int COUNT_FACTOR = 5_000; |
| 19 | + |
| 20 | + final long ptr; |
| 21 | + |
| 22 | + private ByteBuffer idxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_IDX * COUNT_FACTOR).order(ByteOrder.nativeOrder()); |
| 23 | + private ByteBuffer vtxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_VERT * COUNT_FACTOR).order(ByteOrder.nativeOrder()); |
| 24 | + |
| 25 | + /** |
| 26 | + * This class will create a native structure. |
| 27 | + * Call {@link #destroy()} method to manually free used memory. |
| 28 | + */ |
| 29 | + public ImDrawData() { |
| 30 | + ImGui.touch(); |
| 31 | + ptr = nCreate(); |
| 32 | + } |
| 33 | + |
| 34 | + ImDrawData(final long ptr) { |
| 35 | + this.ptr = ptr; |
| 36 | + } |
| 37 | + |
| 38 | + @Override |
| 39 | + public void destroy() { |
| 40 | + nDestroy(ptr); |
45 | 41 | }
|
46 | 42 |
|
47 | 43 | /*JNI
|
48 | 44 | #include <stdint.h>
|
49 | 45 | #include <imgui.h>
|
| 46 | + #include "jni_common.h" |
| 47 | +
|
| 48 | + jfieldID imDrawDataPtrID; |
50 | 49 |
|
51 |
| - jfieldID totalVtxCountID; |
52 |
| - jfieldID totalIdxCountID; |
53 |
| - jfieldID CmdListsCountID; |
54 |
| - jfieldID displayPosXID; |
55 |
| - jfieldID displayPosYID; |
56 |
| - jfieldID displaySizeXID; |
57 |
| - jfieldID displaySizeYID; |
58 |
| - jfieldID framebufferScaleXID; |
59 |
| - jfieldID framebufferScaleYID; |
| 50 | + #define IM_DRAW_DATA ((ImDrawData*)env->GetLongField(object, imDrawDataPtrID)) |
60 | 51 | */
|
61 | 52 |
|
62 | 53 | static native void nInit(); /*
|
63 |
| - jclass jDrawDataClass = env->FindClass("imgui/ImDrawData"); |
| 54 | + jclass jImDrawDataClass = env->FindClass("imgui/ImDrawData"); |
| 55 | + imDrawDataPtrID = env->GetFieldID(jImDrawDataClass, "ptr", "J"); |
| 56 | + */ |
64 | 57 |
|
65 |
| - totalVtxCountID = env->GetFieldID(jDrawDataClass, "totalVtxCount", "I"); |
66 |
| - totalIdxCountID = env->GetFieldID(jDrawDataClass, "totalIdxCount", "I"); |
67 |
| - CmdListsCountID = env->GetFieldID(jDrawDataClass, "cmdListsCount", "I"); |
68 |
| - displayPosXID = env->GetFieldID(jDrawDataClass, "displayPosX", "F"); |
69 |
| - displayPosYID = env->GetFieldID(jDrawDataClass, "displayPosY", "F"); |
70 |
| - displaySizeXID = env->GetFieldID(jDrawDataClass, "displaySizeX", "F"); |
71 |
| - displaySizeYID = env->GetFieldID(jDrawDataClass, "displaySizeY", "F"); |
72 |
| - framebufferScaleXID = env->GetFieldID(jDrawDataClass, "framebufferScaleX", "F"); |
73 |
| - framebufferScaleYID = env->GetFieldID(jDrawDataClass, "framebufferScaleY", "F"); |
| 58 | + private native long nCreate(); /* |
| 59 | + ImDrawData* imDrawData = new ImDrawData(); |
| 60 | + return (intptr_t)imDrawData; |
74 | 61 | */
|
75 | 62 |
|
76 |
| - native void nFillDrawData(Buffer indexBuffer, Buffer vertexBuffer, Buffer cmdBuffer); /* |
77 |
| - ImDrawData* drawData = ImGui::GetDrawData(); |
| 63 | + private native void nDestroy(long ptr); /* |
| 64 | + delete (ImDrawData*)ptr; |
| 65 | + */ |
78 | 66 |
|
79 |
| - if (drawData == NULL) { |
80 |
| - return; |
81 |
| - } |
| 67 | + ///////// Start of Render Methods | Binding |
82 | 68 |
|
83 |
| - int cmdListsCount = drawData->CmdListsCount; |
| 69 | + /** |
| 70 | + * Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback. |
| 71 | + */ |
| 72 | + public native int getCmdListCmdBufferSize(int cmdListIdx); /* |
| 73 | + return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer.Size; |
| 74 | + */ |
| 75 | + |
| 76 | + /** |
| 77 | + * Number of indices (multiple of 3) to be rendered as triangles. |
| 78 | + * Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[]. |
| 79 | + */ |
| 80 | + public native int getCmdListCmdBufferElemCount(int cmdListIdx, int cmdBufferIdx); /* |
| 81 | + return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].ElemCount; |
| 82 | + */ |
| 83 | + |
| 84 | + /** |
| 85 | + * Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates |
| 86 | + */ |
| 87 | + public native void getCmdListCmdBufferClipRect(int cmdListIdx, int cmdBufferIdx, ImVec4 dstImVec4); /* |
| 88 | + Jni::ImVec4Cpy(env, &IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].ClipRect, dstImVec4); |
| 89 | + */ |
| 90 | + |
| 91 | + /** |
| 92 | + * User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. |
| 93 | + * Ignore if never using images or multiple fonts atlas. |
| 94 | + */ |
| 95 | + public native int getCmdListCmdBufferTextureId(int cmdListIdx, int cmdBufferIdx); /* |
| 96 | + return (intptr_t)IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].TextureId; |
| 97 | + */ |
| 98 | + |
| 99 | + /** |
| 100 | + * Start offset in vertex buffer. Pre-1.71 or without ImGuiBackendFlags_RendererHasVtxOffset: always 0. |
| 101 | + * With ImGuiBackendFlags_RendererHasVtxOffset: may be >0 to support meshes larger than 64K vertices with 16-bit indices. |
| 102 | + */ |
| 103 | + public native int getCmdListCmdBufferVtxOffset(int cmdListIdx, int cmdBufferIdx); /* |
| 104 | + return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].VtxOffset; |
| 105 | + */ |
| 106 | + |
| 107 | + /** |
| 108 | + * Start offset in index buffer. Always equal to sum of ElemCount drawn so far. |
| 109 | + */ |
| 110 | + public native int getCmdListCmdBufferIdxOffset(int cmdListIdx, int cmdBufferIdx); /* |
| 111 | + return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].IdxOffset; |
| 112 | + */ |
84 | 113 |
|
85 |
| - // Set values |
86 |
| - env->SetIntField(object, totalVtxCountID, drawData->TotalVtxCount); |
87 |
| - env->SetIntField(object, totalIdxCountID, drawData->TotalIdxCount); |
88 |
| - env->SetIntField(object, CmdListsCountID, cmdListsCount); |
| 114 | + /** |
| 115 | + * Index buffer. Each command consume ImDrawCmd::ElemCount of those |
| 116 | + */ |
| 117 | + public native int getCmdListIdxBufferSize(int cmdListIdx); /* |
| 118 | + return IM_DRAW_DATA->CmdLists[cmdListIdx]->IdxBuffer.Size; |
| 119 | + */ |
89 | 120 |
|
90 |
| - env->SetFloatField(object, displayPosXID, drawData->DisplayPos.x); |
91 |
| - env->SetFloatField(object, displayPosYID, drawData->DisplayPos.y); |
| 121 | + public ByteBuffer getCmdListIdxBufferData(final int cmdListIdx) { |
| 122 | + final int idxBufferCapacity = getCmdListIdxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_IDX; |
| 123 | + if (idxBuffer.capacity() < idxBufferCapacity) { |
| 124 | + idxBuffer = ByteBuffer.allocateDirect(idxBufferCapacity + COUNT_FACTOR).order(ByteOrder.nativeOrder()); |
| 125 | + } |
92 | 126 |
|
93 |
| - env->SetFloatField(object, displaySizeXID, drawData->DisplaySize.x); |
94 |
| - env->SetFloatField(object, displaySizeYID, drawData->DisplaySize.y); |
| 127 | + nGetCmdListIdxBufferData(cmdListIdx, idxBuffer, idxBufferCapacity); |
95 | 128 |
|
96 |
| - env->SetFloatField(object, framebufferScaleXID, drawData->FramebufferScale.x); |
97 |
| - env->SetFloatField(object, framebufferScaleYID, drawData->FramebufferScale.y); |
| 129 | + idxBuffer.position(0); |
| 130 | + idxBuffer.limit(idxBufferCapacity); |
98 | 131 |
|
99 |
| - ImDrawList** drawLists = drawData->CmdLists; |
| 132 | + return idxBuffer; |
| 133 | + } |
100 | 134 |
|
101 |
| - int verticesOffset = 0; |
102 |
| - int indicesOffset = 0; |
103 |
| - int cmdOffset = 0; |
| 135 | + private native void nGetCmdListIdxBufferData(int cmdListIdx, ByteBuffer idxBuffer, int idxBufferCapacity); /* |
| 136 | + memcpy(idxBuffer, IM_DRAW_DATA->CmdLists[cmdListIdx]->IdxBuffer.Data, idxBufferCapacity); |
| 137 | + */ |
104 | 138 |
|
105 |
| - for(int i = 0; i < cmdListsCount; i++) { |
106 |
| - ImDrawList& drawList = *drawLists[i]; |
107 |
| - ImVector<ImDrawCmd>& imDrawCmdList = drawList.CmdBuffer; |
108 |
| - ImVector<ImDrawIdx>& idxBuffer = drawList.IdxBuffer; |
109 |
| - ImVector<ImDrawVert>& vtxBuffer = drawList.VtxBuffer; |
| 139 | + /** |
| 140 | + * Vertex buffer. |
| 141 | + */ |
| 142 | + public native int getCmdListVtxBufferSize(int cmdListIdx); /* |
| 143 | + return IM_DRAW_DATA->CmdLists[cmdListIdx]->VtxBuffer.Size; |
| 144 | + */ |
110 | 145 |
|
111 |
| - float* vertexArrayDest = (float*)vertexBuffer; |
112 |
| - short* indexArrayDest = (short*)indexBuffer; |
| 146 | + public ByteBuffer getCmdListVtxBufferData(final int cmdListIdx) { |
| 147 | + final int vtxBufferCapacity = getCmdListVtxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_VERT; |
| 148 | + if (vtxBuffer.capacity() < vtxBufferCapacity) { |
| 149 | + vtxBuffer = ByteBuffer.allocateDirect(vtxBufferCapacity + COUNT_FACTOR).order(ByteOrder.nativeOrder()); |
| 150 | + } |
113 | 151 |
|
114 |
| - int colorSize = 1; |
115 |
| - int verticesItemSize = (4 + colorSize); |
| 152 | + nGetCmdListVtxBufferData(cmdListIdx, vtxBuffer, vtxBufferCapacity); |
116 | 153 |
|
117 |
| - vertexArrayDest[verticesOffset++] = vtxBuffer.Size; |
| 154 | + vtxBuffer.position(0); |
| 155 | + vtxBuffer.limit(vtxBufferCapacity); |
118 | 156 |
|
119 |
| - // copy vertices to Destination buffer |
120 |
| - for(int j = 0; j < vtxBuffer.Size; j++) { |
121 |
| - ImDrawVert v = vtxBuffer[j]; |
122 |
| - float posX = v.pos.x; |
123 |
| - float posY = v.pos.y; |
124 |
| - float uvX = v.uv.x; |
125 |
| - float uvY = v.uv.y; |
| 157 | + return vtxBuffer; |
| 158 | + } |
126 | 159 |
|
127 |
| - int byteIndex = (j * verticesItemSize) + verticesOffset; |
| 160 | + private native void nGetCmdListVtxBufferData(int cmdListIdx, ByteBuffer vtxBuffer, int vtxBufferCapacity); /* |
| 161 | + memcpy(vtxBuffer, IM_DRAW_DATA->CmdLists[cmdListIdx]->VtxBuffer.Data, vtxBufferCapacity); |
| 162 | + */ |
128 | 163 |
|
129 |
| - float color = 0; |
130 |
| - memcpy(&color, &v.col, 4); // move unsigned int color to float |
| 164 | + ///////// End of Render Methods |
131 | 165 |
|
132 |
| - vertexArrayDest[byteIndex + 0] = posX; |
133 |
| - vertexArrayDest[byteIndex + 1] = posY; |
134 |
| - vertexArrayDest[byteIndex + 2] = uvX; |
135 |
| - vertexArrayDest[byteIndex + 3] = uvY; |
136 |
| - vertexArrayDest[byteIndex + 4] = color; |
137 |
| - } |
138 |
| - verticesOffset += vtxBuffer.Size * verticesItemSize; |
| 166 | + /** |
| 167 | + * Only valid after Render() is called and before the next NewFrame() is called. |
| 168 | + */ |
| 169 | + public native boolean getValid(); /* |
| 170 | + return IM_DRAW_DATA->Valid; |
| 171 | + */ |
139 | 172 |
|
140 |
| - // copy index to destination buffer |
141 |
| - indexArrayDest[indicesOffset++] = idxBuffer.Size; |
| 173 | + /** |
| 174 | + * Number of ImDrawList* to render |
| 175 | + */ |
| 176 | + public native int getCmdListsCount(); /* |
| 177 | + return IM_DRAW_DATA->CmdListsCount; |
| 178 | + */ |
142 | 179 |
|
143 |
| - for(int j = 0; j < idxBuffer.Size; j++) { |
144 |
| - indexArrayDest[j + indicesOffset] = idxBuffer[j]; |
145 |
| - } |
| 180 | + /** |
| 181 | + * For convenience, sum of all ImDrawList's IdxBuffer.Size |
| 182 | + */ |
| 183 | + public native int getTotalIdxCount(); /* |
| 184 | + return IM_DRAW_DATA->TotalIdxCount; |
| 185 | + */ |
146 | 186 |
|
147 |
| - indicesOffset += idxBuffer.Size; |
| 187 | + /** |
| 188 | + * For convenience, sum of all ImDrawList's VtxBuffer.Size |
| 189 | + */ |
| 190 | + public native int getTotalVtxCount(); /* |
| 191 | + return IM_DRAW_DATA->TotalVtxCount; |
| 192 | + */ |
148 | 193 |
|
149 |
| - float* cmdArrayDest = (float*)cmdBuffer; |
| 194 | + /** |
| 195 | + * Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use) |
| 196 | + */ |
| 197 | + public native void getDisplayPos(ImVec2 dstImVec2); /* |
| 198 | + Jni::ImVec2Cpy(env, &IM_DRAW_DATA->DisplayPos, dstImVec2); |
| 199 | + */ |
150 | 200 |
|
151 |
| - cmdArrayDest[cmdOffset++] = imDrawCmdList.Size; |
152 |
| - int bytesOffset = 0; |
153 |
| - int imDrawCmdSize = 1 + 4 + 1; |
| 201 | + /** |
| 202 | + * Size of the viewport to render (== io.DisplaySize for the main viewport) |
| 203 | + * (DisplayPos + DisplaySize == lower-right of the orthogonal projection matrix to use) |
| 204 | + */ |
| 205 | + public native void getDisplaySize(ImVec2 dstImVec2); /* |
| 206 | + Jni::ImVec2Cpy(env, &IM_DRAW_DATA->DisplaySize, dstImVec2); |
| 207 | + */ |
154 | 208 |
|
155 |
| - for (int cmd_i = 0; cmd_i < imDrawCmdList.Size; cmd_i++) { |
156 |
| - const ImDrawCmd* pcmd = &imDrawCmdList[cmd_i]; |
| 209 | + /** |
| 210 | + * Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display. |
| 211 | + */ |
| 212 | + public native void getFramebufferScale(ImVec2 dstImVec2); /* |
| 213 | + Jni::ImVec2Cpy(env, &IM_DRAW_DATA->FramebufferScale, dstImVec2); |
| 214 | + */ |
157 | 215 |
|
158 |
| - float textureID = (float)(intptr_t)pcmd->TextureId; |
159 |
| - float tempArray [6] = { |
160 |
| - (float)pcmd->ElemCount, |
161 |
| - pcmd->ClipRect.x, pcmd->ClipRect.y, |
162 |
| - pcmd->ClipRect.z, pcmd->ClipRect.w, |
163 |
| - textureID |
164 |
| - }; |
| 216 | + // Functions |
165 | 217 |
|
166 |
| - memcpy((cmdArrayDest + (cmd_i * imDrawCmdSize) + cmdOffset), tempArray, imDrawCmdSize * 4); |
167 |
| - bytesOffset = bytesOffset + imDrawCmdSize; |
168 |
| - } |
| 218 | + /** |
| 219 | + * Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. |
| 220 | + * Always prefer indexed rendering! |
| 221 | + */ |
| 222 | + public native void deIndexAllBuffers(); /* |
| 223 | + IM_DRAW_DATA->DeIndexAllBuffers(); |
| 224 | + */ |
169 | 225 |
|
170 |
| - cmdOffset += imDrawCmdList.Size * imDrawCmdSize; |
171 |
| - } |
| 226 | + /** |
| 227 | + * Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than Dear ImGui expects, |
| 228 | + * or if there is a difference between your window resolution and framebuffer resolution. |
| 229 | + */ |
| 230 | + public native void scaleClipRects(float fbScaleX, float fbScaleY); /* |
| 231 | + const ImVec2 fbScale = ImVec2(fbScaleX, fbScaleY); |
| 232 | + IM_DRAW_DATA->ScaleClipRects(fbScale); |
172 | 233 | */
|
173 | 234 | }
|
0 commit comments