1. CIMGUI Wrapper Help

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() 
new topic     » topic index » view message » categorize

2. Re: CIMGUI Wrapper Help

Icy_Viking said...

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

new topic     » goto parent     » topic index » view message » categorize

3. Re: CIMGUI Wrapper Help

ghaberek said...
Icy_Viking said...

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.

new topic     » goto parent     » topic index » view message » categorize

4. Re: CIMGUI Wrapper Help

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

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu