1. CIMGUI Wrapper Help
- Posted by Icy_Viking May 28, 2023
- 842 views
Hello,
I am trying to get a basic example going, but can't figure out how to wrap this one part.
Wrapper code
--I have the flags defined and such, I'm only posting some of the wrapper code, I can post more if needed. public atom gui = 0 ifdef WINDOWS then gui = open_dll("cimgui.dll") elsifdef LINUX or FREEBSD then gui = open_dll("libcimgui.so") elsifdef OSX then gui = open_dll("libcimgui.dylib") end ifdef if gui = -1 then puts(1,"Failed to load cimgui shared library!\n") abort(0) end if public constant ImGuiIO = define_c_struct({ C_INT, --ConfigFlags C_INT, --BackendFlags IMVEC2, --DisplaySize C_FLOAT, --DeltaTime C_FLOAT, --IniSavingRate C_STRING, --IniFilename C_STRING, --LogFilename C_FLOAT, --MouseDoubleClickTime, C_FLOAT, --MouseDoubleClickMaxDist C_FLOAT, --MouseDragThreshold C_FLOAT, --KeyRepeatDelay C_FLOAT, --KeyRepeatRate C_FLOAT, --HoverDelayNormal C_FLOAT, --HoverDelayShort C_POINTER, --UserData C_POINTER, --Fonts C_FLOAT, --FontGlobalScale C_BOOL, --FontAllowUserScaling C_POINTER, --FontDefault IMVEC2, --DisplayFramebufferScale C_BOOL, --ConfigDockingNoSplit C_BOOL, --ConfigDockingWithShift C_BOOL, --ConfigDockingAlwaysTabBar, C_BOOL, --ConfigDockingTransparentPayload C_BOOL, --ConfigViewportsNoAutoMerge C_BOOL, --ConfigViewportsNoTaskBarIcon C_BOOL, --ConfigViewportsNoDecoration C_BOOL, --ConfigViewportsNoDefaultParent, C_BOOL, --MouseDrawCursor C_BOOL, --ConfigMacOSXBehaviors C_BOOL, --ConfigInputTrickleEventQueue C_BOOL, --ConfigInputTextCursorBlink C_BOOL, --ConfigInputTextEnterKeepActive C_BOOL, --ConfigDragClickToInputText C_BOOL, --ConfigWindowResizeFromEdges C_BOOL, --ConfigWindowsMoveFromTitleBarOnly C_FLOAT, --ConfigMemoryCompactTimer C_BOOL, --ConfigDebugBeginReturnValueOnce C_BOOL, --ConfigDebugBeginReturnValueLoop C_STRING, --BackendPlatformName C_STRING, --BackendRenderName C_POINTER, --BackendPlatformUserData C_POINTER, --BackendRendererUserData C_POINTER, --BackendLanguageUserData C_STRING, --GetClipardTextFn C_POINTER, --SetClipboardTextFn C_POINTER, --ClipboardUserData C_POINTER, --SetplatFromImeDataFn C_POINTER, --UnusedPadding C_BOOL, --WantCaptureMouse C_BOOL, --WantCaptureKeyboard C_BOOL, --WantTextInput C_BOOL, --WantSetMousePos C_BOOL, --WantSaveIniSettings C_BOOL, --NavActive C_BOOL, --NavVisible C_FLOAT, --Framerate C_INT, --MetricsRenderVertices C_INT, --MetricsRenderIndices C_INT, --MetricsRenderWindows C_INT, --MetricsActiveWindows C_INT, --MetricsActiveAllocations IMVEC2, --MouseDelta {C_INT,ImGuiKey_COUNT}, --KeyMap {C_BOOL,ImGuiKey_COUNT}, --KeysDown {C_FLOAT,ImGuiNavInput_COUNT}, --NavInputs C_POINTER, --Ctx IMVEC2, --MousePos {C_BOOL,5}, --MouseDown[5] C_FLOAT, --MouseWheel C_FLOAT, --MouseWheelH C_INT, --MouseSource ImGuiMouseSource C_INT, --MousehoveredViewport ImGuiID C_BOOL, --KeyCtrl C_BOOL, --KeyShift C_BOOL, --KeyAlt C_BOOL, --KeySuper C_INT, --KeyMods ImGuiKeyChord {C_INT,ImGuiKey_KeysData_SIZE}, --ImGuiKeyData C_BOOL, --WantCaptureMouseUnlessPopupClose IMVEC2, --MousePosPrev {IMVEC2,5}, --MouseClickPos[5] {C_DOUBLE,5}, --MouseClickedTime[5] {C_BOOL,5}, --MouseClicked[5] {C_BOOL,5}, --MouseDoubleClicked[5] {C_UINT16,5}, --MouseClickedCount[5] {C_UINT16,5}, --MouseClickedLastCount[5] {C_BOOL,5}, --MouseReleased[5] {C_BOOL,5}, --MouseDownOwned[5] {C_BOOL,5}, --MouseDownOwnedUnlessPopupClose[5] C_BOOL, --MouseWheelRequestAxisSwap {C_FLOAT,5}, --MouseDownDuration[5] {C_FLOAT,5}, --MouseDownDurationPrev[5] {IMVEC2,5}, --MouseDragMaxDistanceAbs[5] {C_FLOAT,5}, --MouseDragMiaxDistanceSqr[5] C_FLOAT, --PenPressure C_BOOL, --AppFocusLost C_BOOL, --AppAcceptringEvents C_INT8, --BackendUsingLegacyKeyArrays C_BOOL, --BacendUsingLEgacyNavInputArray C_INT16, --InputQueueSurrogate ImVector_ImWchar --InputQueueCharacters }) export constant xImVec2_ImVec2_Nil = define_c_func(gui,"+ImVec2_ImVec2_Nil",{},C_POINTER) public function ImVec2_ImVec2_Nil() return c_func(xImVec2_ImVec2_Nil,{}) end function export constant xImVec2_destroy = define_c_proc(gui,"+ImVec2_destroy",{C_POINTER}) public procedure ImVec2_destroy(atom self) c_proc(xImVec2_destroy,{self}) end procedure export constant xImVec2_ImVec2_Float = define_c_func(gui,"+ImVec2_ImVec2_Float",{C_FLOAT,C_FLOAT},C_POINTER) public function ImVec2_ImVec2_Float(atom x,atom y) return c_func(xImVec2_ImVec2_Float,{x,y}) end function public constant xigCreateContext = define_c_func(gui,"+igCreateContext",{C_POINTER},C_POINTER) public function igCreateContext(atom shared_font_atlas) return c_func(xigCreateContext,{shared_font_atlas}) end function public constant xigDestroyContext = define_c_proc(gui,"+igDestroyContext",{C_POINTER}) public procedure igDestroyContext(atom ctx) c_proc(xigDestroyContext,{ctx}) end procedure public constant xigGetCurrentContext = define_c_func(gui,"+igGetCurrentContext",{},C_POINTER) public function igGetCurrentContext() return c_func(xigGetCurrentContext,{}) end function public constant xigGetIO = define_c_func(gui,"+igGetIO",{},C_POINTER) public function igGetIO() return c_func(xigGetIO,{}) end function public constant xigNewFrame = define_c_proc(gui,"+igNewFrame",{}) public procedure igNewFrame() c_proc(xigNewFrame,{}) end procedure public constant xigEndFrame = define_c_proc(gui,"+EndFrame",{}) public procedure igEndFrame() c_proc(xigEndFrame,{}) end procedure public constant xigRender = define_c_proc(gui,"+igRender",{}) public procedure igRender() c_proc(xigRender,{}) end procedure public constant xigShowDemoWindow = define_c_proc(gui,"+igShowDemoWindow",{C_POINTER}) public procedure igShowDemoWindow(atom p_open) c_proc(xigShowDemoWindow,{p_open}) end procedure public constant xigGetVersion = define_c_func(gui,"+igGetVersion",{},C_STRING) public function igGetVersion() return c_func(xigGetVersion,{}) end function public constant xigBegin = define_c_func(gui,"+igBegin",{C_STRING,C_POINTER,C_INT},C_BOOL) public function igBegin(sequence name,atom p_open,atom flags) return c_func(xigBegin,{name,p_open,flags}) end function public constant xigEnd = define_c_proc(gui,"+igEnd",{}) public procedure igEnd() c_proc(xigEnd,{}) end procedure public constant xigText = define_c_proc(gui,"+igText",{C_STRING}) public procedure igText(sequence fmt) c_proc(xigText,{fmt}) end procedure
Part of example I'm trying to wrap is here: https://github.com/cimgui/cimgui/blob/docking_inter/test/main.c
Structs here: https://github.com/cimgui/cimgui/blob/docking_inter/cimgui.h
//Part of the ImGuiIO struct struct ImGuiIO { ImGuiConfigFlags ConfigFlags; ImGuiBackendFlags BackendFlags; ImVec2 DisplaySize; }
ImVec2 display_size; display_size.x = 1920; display_size.y = 1080; io->DisplaySize = display_size; Trying to convert this part into Euphoria code using allocate_struct and peek_struct is where I'm kinda stumped
I'm just trying to get a basic frame showing.
5/28/23 - Updated demo. No errors, but nothing comes up.
include std/ffi.e include std/machine.e include cimgui.e procedure main() igCreateContext(NULL) atom io = igGetIO() atom x = 800 atom y = 600 atom vec_size = ImVec2_ImVec2_Float(x,y) --frame needs size or error comes up atom io_s = allocate_struct(ImGuiIO) atom size = peek_struct(io,vec_size) igNewFrame() igBegin("MainWin",NULL,ImGuiWindowFlags_NoTitleBar) igText("Hello World") igEnd() igShowDemoWindow(NULL) igRender() igDestroyContext(NULL) end procedure main()
2. Re: CIMGUI Wrapper Help
- Posted by ghaberek (admin) May 30, 2023
- 798 views
I am trying to get a basic example going, but can't figure out how to wrap this one part.
Wow that ImGuiIO structure is huge! Good thing I'm working on named members for the standard library version of libffi. There's no way you could build sane code around index-counting one hundred members.
That seems like an unfortunate side-effect of the complexities introduced by trying to "flatten" a C++ library (Dear ImGui) down to plain C, but I think I can help with what I've already got in libffi-euphoria.
One thing that's confusing about this code is that they're storing the values in a local struct and then assigning the whole thing to the member at once:
ImVec2 display_size; display_size.x = 1920; display_size.y = 1080; io->DisplaySize = display_size; io->DeltaTime = 1.0f / 60.0f;
That code could be written differently, which helps us understand that we're storing the values in the DisplaySize member of the ImGuiIO structure:
io->DisplaySize.x = 1920; // poke( io + offsetof(DisplaySize) + offsetof(x), 1920 ) io->DisplaySize.y = 1080; // poke( io + offsetof(DisplaySize) + offsetof(y), 1080 )
I added some pseudo code as a comment, to indicate what's basically happening in the background. Hope that makes sense.
You can use poke_member to write the values in one go:
sequence display_size = {1920,1080} poke_member( io, ImGuiIO, 3, display_size ) -- 3 = DisplaySize poke_member( io, ImGuiIO, 4, 1.0 / 60.0 ) -- 4 = DeltaTime
Or simply:
poke_member( io, ImGuiIO, 3, {1920,1080} ) -- 3 = DisplaySize poke_member( io, ImGuiIO, 4, 1.0 / 60.0 ) -- 4 = DeltaTime
For this case, you need to pass a pointer to the variable (&f means "the address of f") so you have to allocate the memory, poke the value, and then pass the address to the function.
One thing to note, however, is that this value is marked as static which means it effectively exists "outside" the for loop or even the main function; it's a part of the program itself.
static float f = 0.0f; igSliderFloat("float", &f, 0.0f, 1.0f, "%.3f", 0);
procedure main() -- allocate this for the whole run atom f = allocate_data( sizeof(C_FLOAT) ) poke_type( f, C_FLOAT, 0.0 ) -- (other code here) -- for i = 1 to 20 do -- (other code here) -- igSliderFloat("float", f, 0.0, 1.0, "%.3f", 0) -- here, f is a pointer to a value in memory -- (more code here) -- end for -- free the memory before we exit free( f ) end procedure
Similar to the DisplaySize and DeltaTime values above, you can use peek_member here:
gText("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io->Framerate, io->Framerate);
In this case I'm storing the value in a local variable to clean up the code and avoid multiple peeks to memory.
atom framerate = peek_member( io, ImGuiIO, 57 ) -- 57 = Framerate gText("Application average %.3f ms/frame (%.1f FPS)", {1000.0 / framerate,framerate})
Hope that helps!
-Greg
3. Re: CIMGUI Wrapper Help
- Posted by Icy_Viking May 30, 2023
- 757 views
I am trying to get a basic example going, but can't figure out how to wrap this one part.
Wow that ImGuiIO structure is huge! Good thing I'm working on named members for the standard library version of libffi. There's no way you could build sane code around index-counting one hundred members.
That seems like an unfortunate side-effect of the complexities introduced by trying to "flatten" a C++ library (Dear ImGui) down to plain C, but I think I can help with what I've already got in libffi-euphoria.
One thing that's confusing about this code is that they're storing the values in a local struct and then assigning the whole thing to the member at once:
ImVec2 display_size; display_size.x = 1920; display_size.y = 1080; io->DisplaySize = display_size; io->DeltaTime = 1.0f / 60.0f;
That code could be written differently, which helps us understand that we're storing the values in the DisplaySize member of the ImGuiIO structure:
io->DisplaySize.x = 1920; // poke( io + offsetof(DisplaySize) + offsetof(x), 1920 ) io->DisplaySize.y = 1080; // poke( io + offsetof(DisplaySize) + offsetof(y), 1080 )
I added some pseudo code as a comment, to indicate what's basically happening in the background. Hope that makes sense.
You can use poke_member to write the values in one go:
sequence display_size = {1920,1080} poke_member( io, ImGuiIO, 3, display_size ) -- 3 = DisplaySize poke_member( io, ImGuiIO, 4, 1.0 / 60.0 ) -- 4 = DeltaTime
Or simply:
poke_member( io, ImGuiIO, 3, {1920,1080} ) -- 3 = DisplaySize poke_member( io, ImGuiIO, 4, 1.0 / 60.0 ) -- 4 = DeltaTime
For this case, you need to pass a pointer to the variable (&f means "the address of f") so you have to allocate the memory, poke the value, and then pass the address to the function.
One thing to note, however, is that this value is marked as static which means it effectively exists "outside" the for loop or even the main function; it's a part of the program itself.
static float f = 0.0f; igSliderFloat("float", &f, 0.0f, 1.0f, "%.3f", 0);
procedure main() -- allocate this for the whole run atom f = allocate_data( sizeof(C_FLOAT) ) poke_type( f, C_FLOAT, 0.0 ) -- (other code here) -- for i = 1 to 20 do -- (other code here) -- igSliderFloat("float", f, 0.0, 1.0, "%.3f", 0) -- here, f is a pointer to a value in memory -- (more code here) -- end for -- free the memory before we exit free( f ) end procedure
Similar to the DisplaySize and DeltaTime values above, you can use peek_member here:
gText("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io->Framerate, io->Framerate);
In this case I'm storing the value in a local variable to clean up the code and avoid multiple peeks to memory.
atom framerate = peek_member( io, ImGuiIO, 57 ) -- 57 = Framerate gText("Application average %.3f ms/frame (%.1f FPS)", {1000.0 / framerate,framerate})
Hope that helps!
-Greg
Thanks Greg, helpful as always. Having named members will be great when structs having tons of members in them.
4. Re: CIMGUI Wrapper Help
- Posted by jmduro May 31, 2023
- 749 views
I don't know if this can be of any help but I put my C structures manager on Github: https://github.com/jm-duro/Structures.
Here is an extract of the raylib demo code:
include std/dll.e include std/machine.e include ../include/structs.e -- Vector2, 2 components public sequence RL_VECTOR2 = "typedef struct Vector2 {" & " float x;" & -- Vector x component " float y;" & -- Vector y component "} Vector2;" constant raylib = open_dll( "raylib.dll" ), xGetWindowPosition = define_c_func( raylib, "+GetWindowPosition", {}, C_POINTER ), $ public function GetWindowPosition() atom p = c_func( xGetWindowPosition, {} ) -- returns {x,y} sequence Vector2 = createStructure(RL_VECTOR2, p) return readStructure(Vector2) end function
Jean-Marc