private static void RenderDrawData(ImDrawDataPtr drawData, RID parent) { // allocate and clear out our CanvasItem pool as needed int neededNodes = 0; for (int i = 0; i < drawData.CmdListsCount; i++) { neededNodes += drawData.CmdListsRange[i].CmdBuffer.Size; } while (_children.Count < neededNodes) { RID newChild = VisualServer.CanvasItemCreate(); VisualServer.CanvasItemSetParent(newChild, parent); VisualServer.CanvasItemSetDrawIndex(newChild, _children.Count); _children.Add(newChild); _meshes.Add(new ArrayMesh()); } // trim unused nodes to reduce draw calls while (_children.Count > neededNodes) { int idx = _children.Count - 1; VisualServer.FreeRid(_children[idx]); _children.RemoveAt(idx); _meshes.RemoveAt(idx); } // render drawData.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale); int nodeN = 0; for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawListPtr cmdList = drawData.CmdListsRange[n]; int idxOffset = 0; int nVert = cmdList.VtxBuffer.Size; Godot.Vector2[] vertices = new Godot.Vector2[nVert]; Godot.Color[] colors = new Godot.Color[nVert]; Godot.Vector2[] uvs = new Godot.Vector2[nVert]; for (int i = 0; i < cmdList.VtxBuffer.Size; i++) { var v = cmdList.VtxBuffer[i]; vertices[i] = new Godot.Vector2(v.pos.X, v.pos.Y); // need to reverse the color bytes byte[] col = BitConverter.GetBytes(v.col); colors[i] = Godot.Color.Color8(col[0], col[1], col[2], col[3]); uvs[i] = new Godot.Vector2(v.uv.X, v.uv.Y); } for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++, nodeN++) { ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi]; int[] indices = new int[drawCmd.ElemCount]; for (int i = idxOffset, j = 0; i < idxOffset + drawCmd.ElemCount; i++, j++) { indices[j] = cmdList.IdxBuffer[i]; } var arrays = new Godot.Collections.Array(); arrays.Resize((int)ArrayMesh.ArrayType.Max); arrays[(int)ArrayMesh.ArrayType.Vertex] = vertices; arrays[(int)ArrayMesh.ArrayType.Color] = colors; arrays[(int)ArrayMesh.ArrayType.TexUv] = uvs; arrays[(int)ArrayMesh.ArrayType.Index] = indices; var mesh = _meshes[nodeN]; while (mesh.GetSurfaceCount() > 0) { mesh.SurfaceRemove(0); } mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); RID child = _children[nodeN]; Texture tex = GetTexture(drawCmd.TextureId); VisualServer.CanvasItemClear(child); VisualServer.CanvasItemSetClip(child, true); VisualServer.CanvasItemSetCustomRect(child, true, new Godot.Rect2( drawCmd.ClipRect.X, drawCmd.ClipRect.Y, drawCmd.ClipRect.Z - drawCmd.ClipRect.X, drawCmd.ClipRect.W - drawCmd.ClipRect.Y) ); VisualServer.CanvasItemAddMesh(child, mesh.GetRid(), null, null, tex.GetRid(), new RID(null)); // why doesn't this quite work? // VisualServer.CanvasItemAddTriangleArray(child, indices, vertices, colors, uvs, null, null, tex.GetRid(), -1, new RID(null)); idxOffset += (int)drawCmd.ElemCount; } } }