Open JekSun97 opened 4 months ago
For the most part, everything should just work in C++. I've been meaning to test this to be sure, so I added ImPlot to the GDExtension example. The important thing is to call ImGui::Godot::SyncImGuiPtrs()
first, because that sets up the ImGuiContext. Otherwise it should be pretty simple to add whatever you want to your build.
I have no plans to add C# or GDScript bindings for any third-party libraries, it's just way too much tedious work to write and maintain that sort of thing. The C# bindings are entirely ImGui.NET, and the GDScript bindings only exist because dear_bindings does the heavy lifting specifically for ImGui.
Thought of an important extra detail while looking at imgui_markdown, which is that fonts can only be accessed after the scene tree is loaded, eg in your node's _ready()
method. So something like imgui_markdown should be initialized there.
Let me know if you have any specific difficulties. ImWindow would be very complicated to support, but its functionality now exists natively in ImGui with its docking and multi-viewport features.
https://github.com/pkdawson/imgui-godot/wiki/CPlusPlus#notes
I added an example of using imgui_markdown, because that's a good way to show how to setup something a little more complex. It's still pretty straightforward, except maybe the few extra lines of code to handle atlas textures properly.
I have no plans to add C# or GDScript bindings for any third-party libraries, it's just way too much tedious work to write and maintain that sort of thing. The C# bindings are entirely ImGui.NET,
One could just use the bindings from the ImGui.NET repo it does contain ImPlot / ImNodes etc. bindings for C#. I just don't know how to tell Godot where to find cimplot.. (btw cimplot and all other C Bindings can be obtained here)
EDIT: New link to my forks for cimplot since the mentioned one couldn't be built and needed to be updated too.
EDIT2: Been struggling for hours now.... Got to the point where a hack between the src from you and hacked in cimgui, cimplot from me runs. HOWEVER.. I always get a nullptr exception here:
ImGuiWindow* Window = G.CurrentWindow;
No clue why.. because commenting out ImPlot::BeginPlot etc. and Godot does not crash and runs without issues....
Thread 1 "Godot_v4.2.2-st" received signal SIGSEGV, Segmentation fault.
0x00007fff49e2d4f2 in ImPlot::BeginPlot (title_id=0x7fffffff93f0 "FPS", size=..., flags=0x0)
at /home/subtixx/Godot/TruckSim/Game/modules/imgui/ImGui.NET-nativebuild/cimplot/implot/implot.cpp:2384
2384 ImGuiWindow* Window = G.CurrentWindow;
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x0
$rbx : 0x00007fffffff9990 → 0x3fa3333300000002
$rcx : 0x00007fffffff92f0 → 0x00000000bf800000
$rdx : 0x0
$rsp : 0x00007fffffff9250 → 0x00007fffc9a6f888 → 0x00007fffc947e0f0 → push rbp
$rbp : 0x00007fffffff92d0 → 0x00007fffffff9300 → 0x00007fffffff93e0 → 0x00007fffffff9470 → 0x00007fffffff94f0 → 0x00007fffffff9790 → 0x00007fffffff9810 → 0x00007fffffff9900
$rsi : 0x00007fffffff92f0 → 0x00000000bf800000
$rdi : 0x00007fffffff93f0 → 0x0000000000535046 → ss add al, 0x4c
$rip : 0x00007fff49e2d4f2 → <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00d0> mov rax, QWORD PTR [rax+0x41b0]
$r8 : 0x00007fffffff93f0 → 0x0000000000535046 → ss add al, 0x4c
$r9 : 0x3
$r10 : 0x0
$r11 : 0x00007fff49e2d422 → <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+0000> push rbp
$r12 : 0x11
$r13 : 0x000000000b698330 → 0x0000000005817de8 → 0x000000000211e130 → cmp BYTE PTR [rip+0x430a2e7], 0x0 # 0x642841e
$r14 : 0x0
$r15 : 0xd
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffff9250│+0x0000: 0x00007fffc9a6f888 → 0x00007fffc947e0f0 → push rbp ← $rsp
0x00007fffffff9258│+0x0008: 0x000000000b0f15e0 → 0x0000000000000000
0x00007fffffff9260│+0x0010: 0x00007fffffff92f0 → 0x00000000bf800000
0x00007fffffff9268│+0x0018: 0x00007fffffff93f0 → 0x0000000000535046 → ss add al, 0x4c
0x00007fffffff9270│+0x0020: 0x0000000000000000
0x00007fffffff9278│+0x0028: 0x00007fffc9a6f888 → 0x00007fffc947e0f0 → push rbp
0x00007fffffff9280│+0x0030: 0x000000000bd3f490 → 0x0000000000000000
0x00007fffffff9288│+0x0038: 0x0000000000000000
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x7fff49e2d4e7 <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00c5> mov rax, QWORD PTR [rax]
0x7fff49e2d4ea <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00c8> mov QWORD PTR [rbp-0x48], rax
0x7fff49e2d4ee <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00cc> mov rax, QWORD PTR [rbp-0x48]
→ 0x7fff49e2d4f2 <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00d0> mov rax, QWORD PTR [rax+0x41b0]
0x7fff49e2d4f9 <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00d7> mov QWORD PTR [rbp-0x40], rax
0x7fff49e2d4fd <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00db> mov rax, QWORD PTR [rbp-0x40]
0x7fff49e2d501 <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00df> movzx eax, BYTE PTR [rax+0x104]
0x7fff49e2d508 <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00e6> test al, al
0x7fff49e2d50a <ImPlot::BeginPlot(char const*, ImVec2 const&, int)+00e8> je 0x7fff49e2d535 <_ZN6ImPlot9BeginPlotEPKcRK6ImVec2i+275>
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:/home/subtixx/G[...]implot.cpp+2384 ────
2379 if (gp.CurrentSubplot != nullptr)
2380 ImGui::PushID(gp.CurrentSubplot->CurrentIdx);
2381
2382 // get globals
2383 ImGuiContext &G = *GImGui;
// Window=0x00007fffffff9290 → [...] → push rbp
→ 2384 ImGuiWindow* Window = G.CurrentWindow;
2385
2386 // skip if needed
2387 if (Window->SkipItems && !gp.CurrentSubplot) {
2388 ResetCtxForNextPlot(GImPlot);
2389 return false;
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "Godot_v4.2.2-st", stopped 0x7fff49e2d4f2 in ImPlot::BeginPlot (), reason: SIGSEGV
[#1] Id 2, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#2] Id 22, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#3] Id 30, Name: "[vkps] Update", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#4] Id 3, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#5] Id 21, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#6] Id 26, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#7] Id 4, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#8] Id 34, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d5d733 in clock_nanosleep (), reason: SIGSEGV
[#9] Id 40, Name: ".NET DebugPipe", stopped 0x7ffff7d87355 in open64 (), reason: SIGSEGV
[#10] Id 5, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#11] Id 6, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#12] Id 14, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#13] Id 7, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#14] Id 16, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#15] Id 8, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#16] Id 29, Name: "[vkcf] Analysis", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#17] Id 9, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#18] Id 10, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#19] Id 11, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#20] Id 12, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#21] Id 13, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#22] Id 15, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#23] Id 27, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#24] Id 32, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d92c57 in select (), reason: SIGSEGV
[#25] Id 17, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#26] Id 18, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#27] Id 19, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#28] Id 20, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#29] Id 23, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#30] Id 24, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#31] Id 25, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#32] Id 28, Name: "[vkrt] Analysis", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#33] Id 31, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#34] Id 37, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#35] Id 33, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d5d733 in clock_nanosleep (), reason: SIGSEGV
[#36] Id 35, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d5d733 in clock_nanosleep (), reason: SIGSEGV
[#37] Id 36, Name: "Godot_v4.2.2-st", stopped 0x7ffff7d5d733 in clock_nanosleep (), reason: SIGSEGV
[#38] Id 38, Name: ".NET SynchManag", stopped 0x7ffff7d8763d in poll (), reason: SIGSEGV
[#39] Id 39, Name: ".NET EventPipe", stopped 0x7ffff7d8763d in poll (), reason: SIGSEGV
[#40] Id 41, Name: ".NET Debugger", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#41] Id 42, Name: ".NET Finalizer", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
[#42] Id 43, Name: ".NET Tiered Com", stopped 0x7ffff7d0ca19 in ?? (), reason: SIGSEGV
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7fff49e2d4f2 → ImPlot::BeginPlot(title_id=0x7fffffff93f0 "FPS", size=@0x7fffffff92f0, flags=0x0)
[#1] 0x7fff49e0bd18 → ImPlot_BeginPlot(title_id=0x7fffffff93f0 "FPS", size={
x = -1,
y = 0
}, flags=0x0)
[#2] 0x7fff4b16b2f7 → mov rcx, QWORD PTR [rbp-0x78]
This is how I "run it":
private readonly List<double> _fps = new List<double>(64);
private double _elapsedTime = 0;
public override void _Ready()
{
base._Ready();
ImGuiSync.SyncPtrs();
ImPlot.CreateContext();
}
public override void _Process(double delta)
{
_elapsedTime += delta;
if (_elapsedTime >= 1.0)
{
_fps.Add(Performance.GetMonitor(Performance.Monitor.TimeFps));
_elapsedTime = 0.0;
}
if (ImGui.Begin("Monitor"))
{
//Performance.TIME_FPS
if (ImPlot.BeginPlot("FPS"))
{
Span<double> fpsSpan = CollectionsMarshal.AsSpan(_fps);
ImPlot.PlotLine("FPS", ref fpsSpan[0], fpsSpan.Length);
ImPlot.EndPlot();
}
}
ImGui.End();
base._Process(delta);
}
@Subtixx You shouldn't need to call SyncPtrs if you have the plugin installed and enabled, it does that automatically.
So the key problem here is that the ImGuiContext is not shared between different DLLs / shared libraries. It needs to be manually synchronized.
https://github.com/ocornut/imgui/blob/29fadad1939ab62adcc5cd9339db7a784de90120/imgui.cpp#L1204-L1213
Try adding this before creating the ImPlot context. I'm just looking at the ImPlot.NET code, haven't tested.
ImPlot.SetImGuiContext(ImGui.GetCurrentContext());
Thank you very much! Didn't know that about Shared Libraries thanks!
ImPlot.SetImGuiContext(ImGui.GetCurrentContext());
This does not fully solve the issue since now I'm crashing here:
if (Window->SkipItems && !gp.CurrentSubplot) {
now Window is null.. But I had a hacky solution for me and for the time being, compiling cimgui with cimplot embedded does not result in a crash anymore.
I've tried making some changes from ImGui.NET to Hexa.NET.ImGui for my personal use, and got imgui/implot/imnodes/imguizmo run successfully. Also it seems that Hexa's nuget package contains Android builds that is missing in ImGui.NET. If anyone is interested can take a look at my fork. https://github.com/maidopi-usagi/imgui-godot
Previously, when I used ImGui in C++, I used various libraries for ImGui, here are some of them https://github.com/thedmd/imgui-node-editor https://github.com/Nelarius/imnodes https://github.com/epezent/implot https://github.com/BalazsJako/ImGuiColorTextEdit https://github.com/aiekick/ImGuiFileDialog https://github.com/enkisoftware/imgui_markdown https://github.com/thennequin/ImWindow
How are things going with this? Should I add everything manually or could I consider adding the most popular ones to the plugin itself?