imgui-bindings 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,296 @@
1
+ require 'ffi'
2
+ require 'sdl2'
3
+ require_relative 'imgui'
4
+
5
+ module ImGui
6
+
7
+ class ImGui_ImplSDL2_Data < FFI::Struct
8
+ layout(
9
+ :Window, :pointer,
10
+ :Time, :uint64,
11
+ :MousePressed, [:bool, 3],
12
+ :MouseCursors, [:pointer, ImGuiMouseCursor_COUNT],
13
+ :ClipboardTextData, :pointer,
14
+ :MouseCanUseGlobalState, :bool
15
+ )
16
+ end
17
+
18
+ def self.ImGui_ImplSDL2_GetBackendData()
19
+ io = ImGuiIO.new(ImGui::GetIO())
20
+ return ImGui_ImplSDL2_Data.new(io[:BackendPlatformUserData])
21
+ end
22
+
23
+ @@g_Window = nil # SDL_Window*
24
+ @@g_Time = 0.0 # UInt64
25
+ @@g_BackendPlatformName = FFI::MemoryPointer.from_string("imgui_impl_sdl")
26
+ @@g_BackendPlatformUserData = nil
27
+
28
+ # [TODO] Support ClipboardText
29
+ # g_ClipboardTextData
30
+ # ImplSDL2_GetClipboardText
31
+ # ImplSDL2_SetClipboardText
32
+
33
+ # [TODO] SDL_MOUSE
34
+ def self.get_sdl2_mousebit(x); return (1 << ((x)-1)); end
35
+
36
+ # [TODO] #define KMOD_CTRL, #define KMOD_SHIFT, #define KMOD_ALT and #define KMOD_GUI
37
+ KMOD_CTRL = SDL2::KMOD_LCTRL|SDL2::KMOD_RCTRL
38
+ KMOD_SHIFT = SDL2::KMOD_LSHIFT|SDL2::KMOD_RSHIFT
39
+ KMOD_ALT = SDL2::KMOD_LALT|SDL2::KMOD_RALT
40
+ KMOD_GUI = SDL2::KMOD_LGUI|SDL2::KMOD_RGUI
41
+
42
+ # [INTERNAL]
43
+ def self.ImplSDL2_UpdateMousePosAndButtons()
44
+ # Update buttons
45
+ io = ImGuiIO.new(ImGui::GetIO())
46
+ bd = ImGui_ImplSDL2_GetBackendData()
47
+ window = bd[:Window]
48
+
49
+ # Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
50
+ if io[:WantSetMousePos]
51
+ SDL2::SDL_WarpMouseInWindow(window, io[:MousePos][:x].to_i, io[:MousePos][:y].to_i)
52
+ else
53
+ io[:MousePos][:x] = -Float::MAX
54
+ io[:MousePos][:y] = -Float::MAX
55
+ end
56
+
57
+ mx = FFI::MemoryPointer.new(:int)
58
+ my = FFI::MemoryPointer.new(:int)
59
+ mouse_buttons = SDL2::SDL_GetMouseState(mx, my)
60
+ io[:MouseDown][0] = bd[:MousePressed][0] || (mouse_buttons & get_sdl2_mousebit(SDL2::SDL_BUTTON_LEFT)) != 0 # If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
61
+ io[:MouseDown][1] = bd[:MousePressed][1] || (mouse_buttons & get_sdl2_mousebit(SDL2::SDL_BUTTON_RIGHT)) != 0
62
+ io[:MouseDown][2] = bd[:MousePressed][2] || (mouse_buttons & get_sdl2_mousebit(SDL2::SDL_BUTTON_MIDDLE)) != 0
63
+ bd[:MousePressed][0] = bd[:MousePressed][1] = bd[:MousePressed][2] = false
64
+
65
+ focused_window = SDL2::SDL_GetKeyboardFocus()
66
+ hover_window = nil
67
+ mouse_window = nil
68
+ if defined?(SDL2::SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH)
69
+ hovered_window = SDL_GetMouseFocus() # This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH enabled.
70
+ mouse_window = (window == focused_window || window == hovered_window) ? window : nil
71
+ else
72
+ mouse_window = (window == focused_window) ? window : nil
73
+ end
74
+ if mouse_window != nil
75
+ if bd[:MouseCanUseGlobalState]
76
+ # SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
77
+ # The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
78
+ # Won't use this workaround on SDL backends that have no global mouse position, like Wayland or RPI
79
+ wx = FFI::MemoryPointer.new(:int)
80
+ wy = FFI::MemoryPointer.new(:int)
81
+ SDL2::SDL_GetWindowPosition(focused_window, wx, wy)
82
+ SDL2::SDL_GetGlobalMouseState(mx, my)
83
+ io[:MousePos][:x] = mx.read(:int).to_f - wx.read(:int).to_f
84
+ io[:MousePos][:y] = my.read(:int).to_f - wy.read(:int).to_f
85
+ else
86
+ io[:MousePos][:x] = mx.read(:int).to_f
87
+ io[:MousePos][:y] = my.read(:int).to_f
88
+ end
89
+ end
90
+
91
+ # SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
92
+ # The function is only supported from SDL 2.0.4 (released Jan 2016)
93
+ any_mouse_button_down = ImGui::IsAnyMouseDown()
94
+ SDL2::SDL_CaptureMouse(any_mouse_button_down ? SDL2::SDL_TRUE : SDL2::SDL_FALSE)
95
+
96
+ # [TODO]
97
+ #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
98
+ end
99
+
100
+ def self.ImplSDL2_UpdateMouseCursor()
101
+ io = ImGuiIO.new(ImGui::GetIO())
102
+ return if (io[:ConfigFlags] & ImGuiConfigFlags_NoMouseCursorChange)
103
+ bd = ImGui_ImplSDL2_GetBackendData()
104
+
105
+ imgui_cursor = ImGui::GetMouseCursor()
106
+ if io[:MouseDrawCursor] || imgui_cursor == ImGuiMouseCursor_None
107
+ # Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
108
+ SDL2::SDL_ShowCursor(SDL2::SDL_FALSE)
109
+ else
110
+ # Show OS mouse cursor
111
+ SDL2::SDL_SetCursor(bd[:MouseCursors][imgui_cursor] ? bd[:MouseCursors][imgui_cursor] : bd[:MouseCursors][ImGuiMouseCursor_Arrow])
112
+ SDL2::SDL_ShowCursor(SDL2::SDL_TRUE)
113
+ end
114
+ end
115
+
116
+ #
117
+ # [TODO] Support ImplSDL2_UpdateGamepads
118
+ #
119
+
120
+ def self.ImplSDL2_Shutdown()
121
+ io = ImGuiIO.new(ImGui::GetIO())
122
+ bd = ImGui_ImplSDL2_GetBackendData()
123
+
124
+ # [TODO] Destroy last known clipboard data
125
+
126
+ @@g_Window = nil
127
+ ImGuiMouseCursor_COUNT.times do |cursor_n|
128
+ SDL2::SDL_FreeCursor(bd[:MouseCursors][cursor_n])
129
+ bd[:MouseCursors][cursor_n] = nil
130
+ end
131
+ @@g_BackendPlatformUserData = nil
132
+ end
133
+
134
+ def self.ImplSDL2_NewFrame()
135
+ io = ImGuiIO.new(ImGui::GetIO())
136
+ bd = ImGui_ImplSDL2_GetBackendData()
137
+
138
+ unless io[:Fonts].IsBuilt()
139
+ puts "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."
140
+ end
141
+
142
+ # Setup display size (every frame to accommodate for window resizing)
143
+ w = ' ' * 4
144
+ h = ' ' * 4
145
+ display_w = ' ' * 4
146
+ display_h = ' ' * 4
147
+ SDL2::SDL_GetWindowSize(bd[:Window], w, h)
148
+ SDL2::SDL_GL_GetDrawableSize(bd[:Window], display_w, display_h)
149
+
150
+ w = w.unpack1('L')
151
+ h = h.unpack1('L')
152
+ display_size = ImVec2.new
153
+ display_size[:x] = w.to_f
154
+ display_size[:y] = h.to_f
155
+ io[:DisplaySize] = display_size
156
+
157
+ if w > 0 && h > 0
158
+ fb_scale = ImVec2.new
159
+ fb_scale[:x] = display_w.unpack1('L').to_f / w
160
+ fb_scale[:y] = display_h.unpack1('L').to_f / h
161
+ io[:DisplayFramebufferScale] = fb_scale
162
+ end
163
+
164
+ # Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
165
+ frequency = SDL2::SDL_GetPerformanceFrequency()
166
+ current_time = SDL2::SDL_GetPerformanceCounter()
167
+
168
+ io[:DeltaTime] = @@g_Time > 0 ? ((current_time - @@g_Time).to_f / frequency) : (1.0/60.0)
169
+ @@g_Time = current_time
170
+
171
+ ImplSDL2_UpdateMousePosAndButtons()
172
+ ImplSDL2_UpdateMouseCursor()
173
+
174
+ # [TODO] update gamepads
175
+ end
176
+
177
+ # You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
178
+ # - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
179
+ # - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
180
+ # Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
181
+ # If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
182
+ def self.ImplSDL2_ProcessEvent(event)
183
+ io = ImGuiIO.new(ImGui::GetIO())
184
+ bd = ImGui_ImplSDL2_GetBackendData()
185
+
186
+ case event[:type]
187
+
188
+ when SDL2::SDL_MOUSEWHEEL
189
+ io[:MouseWheelH] += 1 if (event[:wheel][:x] > 0)
190
+ io[:MouseWheelH] -= 1 if (event[:wheel][:x] < 0)
191
+ io[:MouseWheel] += 1 if (event[:wheel][:y] > 0)
192
+ io[:MouseWheel] -= 1 if (event[:wheel][:y] < 0)
193
+ return true
194
+
195
+ when SDL2::SDL_MOUSEBUTTONDOWN
196
+ bd[:MousePressed][0] = true if event[:button][:button] == SDL2::SDL_BUTTON_LEFT
197
+ bd[:MousePressed][1] = true if event[:button][:button] == SDL2::SDL_BUTTON_RIGHT
198
+ bd[:MousePressed][2] = true if event[:button][:button] == SDL2::SDL_BUTTON_MIDDLE
199
+ return true
200
+
201
+ when SDL2::SDL_TEXTINPUT
202
+ io.AddInputCharactersUTF8(event[:text][:text])
203
+ return true
204
+
205
+ when SDL2::SDL_KEYDOWN, SDL2::SDL_KEYUP
206
+ key = event[:key][:keysym][:scancode]
207
+ # IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown))
208
+ io[:KeysDown][key] = (event[:type] == SDL2::SDL_KEYDOWN)
209
+ io[:KeyShift] = ((SDL2::SDL_GetModState() & KMOD_SHIFT) != 0)
210
+ io[:KeyCtrl] = ((SDL2::SDL_GetModState() & KMOD_CTRL) != 0)
211
+ io[:KeyAlt] = ((SDL2::SDL_GetModState() & KMOD_ALT) != 0)
212
+ io[:KeySuper] = ((SDL2::SDL_GetModState() & KMOD_GUI) != 0) # [TODO] io.KeySuper = false on _WIN32
213
+ return true
214
+ end
215
+
216
+ return false
217
+ end
218
+
219
+ def self.ImplSDL2_Init(window)
220
+
221
+ @@g_Window = window
222
+ @@g_Time = 0
223
+
224
+ @@g_BackendPlatformUserData = ImGui_ImplSDL2_Data.new
225
+ @@g_BackendPlatformUserData[:Window] = window
226
+
227
+ io = ImGuiIO.new(ImGui::GetIO())
228
+
229
+ io[:BackendPlatformUserData] = @@g_BackendPlatformUserData
230
+ io[:BackendPlatformName] = @@g_BackendPlatformName
231
+ io[:BackendFlags] |= ImGuiBackendFlags_HasMouseCursors # We can honor GetMouseCursor() values (optional)
232
+ io[:BackendFlags] |= ImGuiBackendFlags_HasSetMousePos # We can honor io.WantSetMousePos requests (optional, rarely used)
233
+
234
+ # Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
235
+ io[:KeyMap][ImGuiKey_Tab] = SDL2::SDL_SCANCODE_TAB
236
+ io[:KeyMap][ImGuiKey_LeftArrow] = SDL2::SDL_SCANCODE_LEFT
237
+ io[:KeyMap][ImGuiKey_RightArrow] = SDL2::SDL_SCANCODE_RIGHT
238
+ io[:KeyMap][ImGuiKey_UpArrow] = SDL2::SDL_SCANCODE_UP
239
+ io[:KeyMap][ImGuiKey_DownArrow] = SDL2::SDL_SCANCODE_DOWN
240
+ io[:KeyMap][ImGuiKey_PageUp] = SDL2::SDL_SCANCODE_PAGEUP
241
+ io[:KeyMap][ImGuiKey_PageDown] = SDL2::SDL_SCANCODE_PAGEDOWN
242
+ io[:KeyMap][ImGuiKey_Home] = SDL2::SDL_SCANCODE_HOME
243
+ io[:KeyMap][ImGuiKey_End] = SDL2::SDL_SCANCODE_END
244
+ io[:KeyMap][ImGuiKey_Insert] = SDL2::SDL_SCANCODE_INSERT
245
+ io[:KeyMap][ImGuiKey_Delete] = SDL2::SDL_SCANCODE_DELETE
246
+ io[:KeyMap][ImGuiKey_Backspace] = SDL2::SDL_SCANCODE_BACKSPACE
247
+ io[:KeyMap][ImGuiKey_Space] = SDL2::SDL_SCANCODE_SPACE
248
+ io[:KeyMap][ImGuiKey_Enter] = SDL2::SDL_SCANCODE_RETURN
249
+ io[:KeyMap][ImGuiKey_Escape] = SDL2::SDL_SCANCODE_ESCAPE
250
+ io[:KeyMap][ImGuiKey_KeyPadEnter] = SDL2::SDL_SCANCODE_RETURN2
251
+ io[:KeyMap][ImGuiKey_A] = SDL2::SDL_SCANCODE_A
252
+ io[:KeyMap][ImGuiKey_C] = SDL2::SDL_SCANCODE_C
253
+ io[:KeyMap][ImGuiKey_V] = SDL2::SDL_SCANCODE_V
254
+ io[:KeyMap][ImGuiKey_X] = SDL2::SDL_SCANCODE_X
255
+ io[:KeyMap][ImGuiKey_Y] = SDL2::SDL_SCANCODE_Y
256
+ io[:KeyMap][ImGuiKey_Z] = SDL2::SDL_SCANCODE_Z
257
+
258
+ # [TODO] Support ClipboardText
259
+
260
+ bd = ImGui_ImplSDL2_GetBackendData()
261
+
262
+ bd[:MouseCursors][ImGuiMouseCursor_Arrow] = SDL2::SDL_CreateSystemCursor(SDL2::SDL_SYSTEM_CURSOR_ARROW)
263
+ bd[:MouseCursors][ImGuiMouseCursor_TextInput] = SDL2::SDL_CreateSystemCursor(SDL2::SDL_SYSTEM_CURSOR_IBEAM)
264
+ bd[:MouseCursors][ImGuiMouseCursor_ResizeAll] = SDL2::SDL_CreateSystemCursor(SDL2::SDL_SYSTEM_CURSOR_SIZEALL)
265
+ bd[:MouseCursors][ImGuiMouseCursor_ResizeNS] = SDL2::SDL_CreateSystemCursor(SDL2::SDL_SYSTEM_CURSOR_SIZENS)
266
+ bd[:MouseCursors][ImGuiMouseCursor_ResizeEW] = SDL2::SDL_CreateSystemCursor(SDL2::SDL_SYSTEM_CURSOR_SIZEWE)
267
+ bd[:MouseCursors][ImGuiMouseCursor_ResizeNESW] = SDL2::SDL_CreateSystemCursor(SDL2::SDL_SYSTEM_CURSOR_SIZENESW)
268
+ bd[:MouseCursors][ImGuiMouseCursor_ResizeNWSE] = SDL2::SDL_CreateSystemCursor(SDL2::SDL_SYSTEM_CURSOR_SIZENWSE)
269
+ bd[:MouseCursors][ImGuiMouseCursor_Hand] = SDL2::SDL_CreateSystemCursor(SDL2::SDL_SYSTEM_CURSOR_HAND)
270
+ bd[:MouseCursors][ImGuiMouseCursor_NotAllowed] = SDL2::SDL_CreateSystemCursor(SDL2::SDL_SYSTEM_CURSOR_NO)
271
+
272
+ =begin
273
+ #ifdef _WIN32
274
+ SDL_SysWMinfo info;
275
+ SDL_VERSION(&info.version);
276
+ if (SDL_GetWindowWMInfo(window, &info))
277
+ io.ImeWindowHandle = info.info.win.window;
278
+ #else
279
+ =end
280
+
281
+ =begin
282
+ sdl_backend = SDL_GetCurrentVideoDriver().read_string
283
+ global_mouse_whitelist = [ "windows", "cocoa", "x11", "DIVE", "VMAN" ]
284
+ bd[:MouseCanUseGlobalState] = false
285
+ global_mouse_whitelist.each do |elem|
286
+ bd[:MouseCanUseGlobalState] = true if sdl_backend == elem
287
+ end
288
+ =end
289
+ if defined?(SDL2::SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH)
290
+ SDL_SetHint(SDL2::SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1")
291
+ end
292
+
293
+ return true
294
+ end
295
+
296
+ end
@@ -0,0 +1,201 @@
1
+ require 'ffi'
2
+ require 'sdl2'
3
+ require_relative 'imgui'
4
+
5
+ module ImGui
6
+
7
+ class ImGui_ImplSDLRenderer_Data < FFI::Struct
8
+ layout(
9
+ :SDLRenderer, :pointer,
10
+ :FontTexture, :pointer
11
+ )
12
+ end
13
+
14
+ def self.ImGui_ImplSDLRenderer_GetBackendData()
15
+ if ImGui::GetCurrentContext() != nil
16
+ io = ImGuiIO.new(ImGui::GetIO())
17
+ instance = ImGui_ImplSDLRenderer_Data.new(io[:BackendRendererUserData])
18
+ return instance
19
+ else
20
+ return nil
21
+ end
22
+ end
23
+
24
+ @@g_BackendRendererName = FFI::MemoryPointer.from_string("imgui_impl_sdlrenderer")
25
+ @@g_BackendRendererUserData = nil
26
+
27
+ def self.ImplSDLRenderer_Init(renderer)
28
+ io = ImGuiIO.new(ImGui::GetIO())
29
+
30
+ # Setup backend capabilities flags
31
+
32
+ io[:BackendRendererName] = @@g_BackendRendererName
33
+
34
+ @@g_BackendRendererUserData = ImGui_ImplSDLRenderer_Data.new
35
+ @@g_BackendRendererUserData[:SDLRenderer] = renderer
36
+ @@g_BackendRendererUserData[:FontTexture] = nil
37
+ io[:BackendRendererUserData] = @@g_BackendRendererUserData
38
+
39
+ io[:BackendFlags] |= ImGuiBackendFlags_RendererHasVtxOffset # We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
40
+
41
+ return true
42
+ end
43
+
44
+ def self.ImplSDLRenderer_Shutdown()
45
+ ImplSDLRenderer_DestroyDeviceObjects()
46
+ io = ImGuiIO.new(ImGui::GetIO())
47
+ io[:BackendRendererName] = nil
48
+ io[:BackendRendererUserData] = nil
49
+ @@g_BackendRendererUserData = nil
50
+ end
51
+
52
+ # [Internal]
53
+ def self.ImplSDLRenderer_SetupRenderState()
54
+ bd = ImGui_ImplSDLRenderer_GetBackendData()
55
+
56
+ # Clear out any viewports and cliprect set by the user
57
+ # FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
58
+ SDL_RenderSetViewport(bd[:SDLRenderer], nil)
59
+ SDL_RenderSetClipRect(bd[:SDLRenderer], nil)
60
+ end
61
+
62
+ def self.ImplSDLRenderer_NewFrame()
63
+ io = ImGuiIO.new(ImGui::GetIO())
64
+ bd = ImGui_ImplSDLRenderer_GetBackendData()
65
+ ImGui::ImplSDLRenderer_CreateDeviceObjects() if bd[:FontTexture] == nil
66
+ end
67
+
68
+ def self.ImplSDLRenderer_RenderDrawData(draw_data_raw)
69
+ draw_data = ImDrawData.new(draw_data_raw)
70
+ bd = ImGui_ImplSDLRenderer_GetBackendData()
71
+
72
+ # If there's a scale factor set by the user, use that instead
73
+ # If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass
74
+ # to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here.
75
+ rsx = FFI::MemoryPointer.new :float
76
+ rsy = FFI::MemoryPointer.new :float
77
+ SDL_RenderGetScale(bd[:SDLRenderer], rsx, rsy)
78
+ render_scale = ImVec2.create(0, 0)
79
+ render_scale[:x] = (rsx.read_float() == 1.0) ? draw_data[:FramebufferScale][:x] : 1.0
80
+ render_scale[:y] = (rsy.read_float() == 1.0) ? draw_data[:FramebufferScale][:y] : 1.0
81
+
82
+ # Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
83
+ fb_width = (draw_data[:DisplaySize][:x] * render_scale[:x]).to_i
84
+ fb_height = (draw_data[:DisplaySize][:y] * render_scale[:y]).to_i
85
+ return if fb_width == 0 || fb_height == 0
86
+
87
+ # Backup SDL_Renderer state that will be modified to restore it afterwards
88
+ oldViewport = SDL_Rect.new
89
+ oldClipEnabled = FFI::MemoryPointer.new :bool
90
+ oldClipRect = SDL_Rect.new
91
+
92
+ oldClipEnabled = (SDL_RenderIsClipEnabled(bd[:SDLRenderer]) == SDL_TRUE)
93
+ SDL_RenderGetViewport(bd[:SDLRenderer], oldViewport)
94
+ SDL_RenderGetClipRect(bd[:SDLRenderer], oldClipRect)
95
+
96
+ # Will project scissor/clipping rectangles into framebuffer space
97
+ clip_off = draw_data[:DisplayPos] # (0,0) unless using multi-viewports
98
+ clip_scale = render_scale
99
+
100
+ # Render command lists
101
+ ImplSDLRenderer_SetupRenderState()
102
+ draw_data[:CmdListsCount].times do |n|
103
+ cmd_list = ImDrawList.new((draw_data[:CmdLists].pointer + FFI.type_size(:pointer) * n).read_pointer)
104
+ vtx_buffer = cmd_list[:VtxBuffer][:Data] # const ImDrawVert*
105
+ idx_buffer = cmd_list[:IdxBuffer][:Data] # const ImDrawIdx*
106
+
107
+ cmd_list[:CmdBuffer][:Size].times do |cmd_i|
108
+ pcmd = ImDrawCmd.new(cmd_list[:CmdBuffer][:Data] + ImDrawCmd.size * cmd_i) # const ImDrawCmd*
109
+ if pcmd[:UserCallback] != nil
110
+ # [TODO] Handle user callback (Ref.: https://github.com/ffi/ffi/wiki/Callbacks )
111
+
112
+ # User callback, registered via ImDrawList::AddCallback()
113
+ # (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
114
+ # if pcmd[:UserCallback] == :ImDrawCallback_ResetRenderState
115
+ ImGui_ImplSDLRenderer_SetupRenderState()
116
+ # else
117
+ # pcmd[:UserCallback](cmd_list, pcmd)
118
+ # end
119
+ else
120
+ clip_min = ImVec2.create((pcmd[:ClipRect][:x] - clip_off[:x]) * clip_scale[:x], (pcmd[:ClipRect][:y] - clip_off[:y]) * clip_scale[:y])
121
+ clip_max = ImVec2.create((pcmd[:ClipRect][:z] - clip_off[:x]) * clip_scale[:x], (pcmd[:ClipRect][:w] - clip_off[:y]) * clip_scale[:y])
122
+
123
+ clip_min[:x] = 0.0 if clip_min[:x] < 0.0
124
+ clip_min[:y] = 0.0 if clip_min[:y] < 0.0
125
+ clip_max[:x] = fb_width.to_f if clip_max[:x] > fb_width
126
+ clip_max[:y] = fb_height.to_f if clip_max[:y] > fb_height
127
+ next if (clip_max[:x] <= clip_min[:x] || clip_max[:y] <= clip_min[:y])
128
+
129
+ r = SDL_Rect.new
130
+ r[:x] = clip_min[:x].to_i
131
+ r[:y] = clip_min[:y].to_i
132
+ r[:w] = (clip_max[:x] - clip_min[:x]).to_i
133
+ r[:h] = (clip_max[:y] - clip_min[:y]).to_i
134
+
135
+ SDL_RenderSetClipRect(bd[:SDLRenderer], r.to_ptr)
136
+
137
+ xy = vtx_buffer + (pcmd[:VtxOffset] + ImDrawVert.offset_of(:pos))
138
+ uv = vtx_buffer + (pcmd[:VtxOffset] + ImDrawVert.offset_of(:uv))
139
+ color = vtx_buffer + (pcmd[:VtxOffset] + ImDrawVert.offset_of(:col))
140
+
141
+ SDL_RenderGeometryRaw(bd[:SDLRenderer], pcmd[:TextureId],
142
+ xy, ImDrawVert.size,
143
+ color, ImDrawVert.size,
144
+ uv, ImDrawVert.size,
145
+ cmd_list[:VtxBuffer][:Size] - pcmd[:VtxOffset],
146
+ idx_buffer + FFI.type_size(:ImDrawIdx) * pcmd[:IdxOffset], pcmd[:ElemCount], FFI.type_size(:ImDrawIdx)) # FFI.type_size(:ImDrawIdx) == FFI::Type::UINT16.size
147
+
148
+ # Restore modified SDL_Renderer state
149
+ SDL_RenderSetViewport(bd[:SDLRenderer], oldViewport)
150
+ SDL_RenderSetClipRect(bd[:SDLRenderer], oldClipEnabled ? oldClipRect : nil)
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ # Called by Init/NewFrame/Shutdown
157
+ def self.ImplSDLRenderer_CreateFontsTexture()
158
+ io = ImGuiIO.new(ImGui::GetIO())
159
+ bd = ImGui_ImplSDLRenderer_GetBackendData()
160
+
161
+ # Build texture atlas
162
+ pixels = FFI::MemoryPointer.new :pointer
163
+ width = FFI::MemoryPointer.new :int
164
+ height = FFI::MemoryPointer.new :int
165
+ io[:Fonts].GetTexDataAsRGBA32(pixels, width, height, nil) # Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
166
+
167
+ # Upload texture to graphics system
168
+ bd[:FontTexture] = SDL_CreateTexture(bd[:SDLRenderer], SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width.read_int, height.read_int)
169
+ if bd[:FontTexture] == nil
170
+ SDL_Log("error creating texture")
171
+ return false
172
+ end
173
+
174
+ SDL_UpdateTexture(bd[:FontTexture], nil, pixels.read_pointer, 4 * width.read_int)
175
+ SDL_SetTextureBlendMode(bd[:FontTexture], SDL_BLENDMODE_BLEND)
176
+
177
+ # Store our identifier
178
+ io[:Fonts].SetTexID(bd[:FontTexture])
179
+
180
+ return true
181
+ end
182
+
183
+ def self.ImplSDLRenderer_DestroyFontsTexture()
184
+ io = ImGuiIO.new(ImGui::GetIO())
185
+ bd = ImGui_ImplSDLRenderer_GetBackendData()
186
+ if bd[:FontTexture] != nil
187
+ io[:Fonts].SetTexID(nil)
188
+ SDL_DestroyTexture(bd[:FontTexture])
189
+ bd[:FontTexture] = nil
190
+ end
191
+ end
192
+
193
+ def self.ImplSDLRenderer_CreateDeviceObjects()
194
+ return ImGui::ImplSDLRenderer_CreateFontsTexture()
195
+ end
196
+
197
+ def self.ImplSDLRenderer_DestroyDeviceObjects()
198
+ ImGui::ImplSDLRenderer_DestroyFontsTexture()
199
+ end
200
+
201
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: imgui-bindings
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - vaiorabbit
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-12-31 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: 'Ruby bindings for Dear ImGui.
14
+
15
+ '
16
+ email:
17
+ - vaiorabbit@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ChangeLog
23
+ - LICENSE.txt
24
+ - README.md
25
+ - lib/imgui.dll
26
+ - lib/imgui.dylib
27
+ - lib/imgui.rb
28
+ - lib/imgui_debug.dll
29
+ - lib/imgui_debug.dylib
30
+ - lib/imgui_impl_glfw.rb
31
+ - lib/imgui_impl_opengl2.rb
32
+ - lib/imgui_impl_opengl3.rb
33
+ - lib/imgui_impl_sdl2.rb
34
+ - lib/imgui_impl_sdlrenderer.rb
35
+ homepage: https://github.com/vaiorabbit/ruby-imgui
36
+ licenses:
37
+ - Zlib
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.6.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.3.3
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Bindings for Dear ImGui
58
+ test_files: []