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.
- checksums.yaml +7 -0
- data/ChangeLog +256 -0
- data/LICENSE.txt +21 -0
- data/README.md +90 -0
- data/lib/imgui.dll +0 -0
- data/lib/imgui.dylib +0 -0
- data/lib/imgui.rb +5414 -0
- data/lib/imgui_debug.dll +0 -0
- data/lib/imgui_debug.dylib +0 -0
- data/lib/imgui_impl_glfw.rb +240 -0
- data/lib/imgui_impl_opengl2.rb +213 -0
- data/lib/imgui_impl_opengl3.rb +513 -0
- data/lib/imgui_impl_sdl2.rb +296 -0
- data/lib/imgui_impl_sdlrenderer.rb +201 -0
- metadata +58 -0
data/lib/imgui_debug.dll
ADDED
Binary file
|
Binary file
|
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'opengl'
|
3
|
+
require 'glfw'
|
4
|
+
|
5
|
+
require_relative 'imgui'
|
6
|
+
|
7
|
+
module ImGui
|
8
|
+
|
9
|
+
@@g_Window = nil # GLFWwindow*
|
10
|
+
@@g_Time = 0.0 # double
|
11
|
+
@@g_MouseWindow = nil # GLFWwindow*
|
12
|
+
@@g_MouseJustPressed = [false, false, false, false, false]
|
13
|
+
@@g_MouseCursors = Array.new(ImGuiMouseCursor_COUNT) { 0 }
|
14
|
+
|
15
|
+
@@g_BackendPlatformName = FFI::MemoryPointer.from_string("imgui_impl_glfw")
|
16
|
+
|
17
|
+
# Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
|
18
|
+
@@g_PrevUserCallbackCursorEnter = nil
|
19
|
+
@@g_PrevUserCallbackMousebutton = nil
|
20
|
+
@@g_PrevUserCallbackScroll = nil
|
21
|
+
@@g_PrevUserCallbackKey = nil
|
22
|
+
@@g_PrevUserCallbackChar = nil
|
23
|
+
|
24
|
+
@@ImplGlfw_MouseButtonCallback = GLFW::create_callback(:GLFWmousebuttonfun) do |window, button, action, mods|
|
25
|
+
unless @@g_PrevUserCallbackMousebutton.null?
|
26
|
+
userfunc = Fiddle::Function.new(@@g_PrevUserCallbackMousebutton, GLFWmousebuttonfun_cb_args, GLFWmousebuttonfun_cb_retval)
|
27
|
+
userfunc.call(window, button, action, mods)
|
28
|
+
end
|
29
|
+
|
30
|
+
if action == GLFW_PRESS && button >= 0 && button < @@g_MouseJustPressed.size
|
31
|
+
@@g_MouseJustPressed[button] = true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
@@ImplGlfw_ScrollCallback = GLFW::create_callback(:GLFWscrollfun) do |window, xoffset, yoffset|
|
36
|
+
unless @@g_PrevUserCallbackScroll.null?
|
37
|
+
userfunc = Fiddle::Function.new(@@g_PrevUserCallbackScroll, GLFWscrollfun_cb_args, GLFWscrollfun_cb_retval)
|
38
|
+
userfunc.call(window, xoffset, yoffset)
|
39
|
+
end
|
40
|
+
|
41
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
42
|
+
io[:MouseWheelH] += xoffset.to_f
|
43
|
+
io[:MouseWheel] += yoffset.to_f
|
44
|
+
end
|
45
|
+
|
46
|
+
@@ImplGlfw_KeyCallback = GLFW::create_callback(:GLFWkeyfun) do |window, key, scancode, action, mods|
|
47
|
+
unless @@g_PrevUserCallbackKey.null?
|
48
|
+
userfunc = Fiddle::Function.new(@@g_PrevUserCallbackKey, GLFWkeyfun_cb_args, GLFWkeyfun_cb_retval)
|
49
|
+
userfunc.call(window, key, scancode, action, mods)
|
50
|
+
end
|
51
|
+
|
52
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
53
|
+
io[:KeysDown][key] = true if action == GLFW_PRESS
|
54
|
+
io[:KeysDown][key] = false if action == GLFW_RELEASE
|
55
|
+
|
56
|
+
# Modifiers are not reliable across systems
|
57
|
+
io[:KeyCtrl] = io[:KeysDown][GLFW_KEY_LEFT_CONTROL] || io[:KeysDown][GLFW_KEY_RIGHT_CONTROL]
|
58
|
+
io[:KeyShift] = io[:KeysDown][GLFW_KEY_LEFT_SHIFT] || io[:KeysDown][GLFW_KEY_RIGHT_SHIFT]
|
59
|
+
io[:KeyAlt] = io[:KeysDown][GLFW_KEY_LEFT_ALT] || io[:KeysDown][GLFW_KEY_RIGHT_ALT]
|
60
|
+
io[:KeySuper] = io[:KeysDown][GLFW_KEY_LEFT_SUPER] || io[:KeysDown][GLFW_KEY_RIGHT_SUPER]
|
61
|
+
end
|
62
|
+
|
63
|
+
@@ImGui_ImplGlfw_CursorEnterCallback = GLFW::create_callback(:GLFWcursorenterfun) do |window, entered|
|
64
|
+
unless @@g_PrevUserCallbackCursorEnter.null?
|
65
|
+
userfunc = Fiddle::Function.new(@@g_PrevUserCallbackCursorEnter, GLFWcursorenterfun_cb_args, GLFWcursorenterfun_cb_retval)
|
66
|
+
userfunc.call(window, entered)
|
67
|
+
end
|
68
|
+
|
69
|
+
@@g_MouseWindow = window if entered
|
70
|
+
@@g_MouseWindow = nil if (!entered && @@g_MouseWindow == window)
|
71
|
+
end
|
72
|
+
|
73
|
+
@@ImplGlfw_CharCallback = GLFW::create_callback(:GLFWcharfun) do |window, c|
|
74
|
+
unless @@g_PrevUserCallbackChar.null?
|
75
|
+
@@g_PrevUserCallbackChar.call(window, c)
|
76
|
+
end
|
77
|
+
|
78
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
79
|
+
io.AddInputCharacter(c);
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.ImplGlfw_UpdateMousePosAndButtons()
|
83
|
+
# Update buttons
|
84
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
85
|
+
io[:MouseDown].size.times do |i|
|
86
|
+
# 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.
|
87
|
+
io[:MouseDown][i] = (@@g_MouseJustPressed[i] || glfwGetMouseButton(@@g_Window, i) != 0)
|
88
|
+
@@g_MouseJustPressed[i] = false
|
89
|
+
end
|
90
|
+
|
91
|
+
focused = glfwGetWindowAttrib(@@g_Window, GLFW_FOCUSED) != 0
|
92
|
+
mouse_window = (@@g_MouseWindow == @@g_Window || focused) ? @@g_Window : nil
|
93
|
+
|
94
|
+
# Update mouse position
|
95
|
+
mouse_pos_backup = io[:MousePos]
|
96
|
+
io[:MousePos][:x] = -Float::MAX
|
97
|
+
io[:MousePos][:y] = -Float::MAX
|
98
|
+
if io[:WantSetMousePos]
|
99
|
+
if focused
|
100
|
+
glfwSetCursorPos(@@g_Window, mouse_pos_backup[:x].to_f, mouse_pos_backup[:y].to_f)
|
101
|
+
end
|
102
|
+
elsif @@g_MouseWindow != nil
|
103
|
+
mouse_x = ' ' * 8
|
104
|
+
mouse_y = ' ' * 8
|
105
|
+
glfwGetCursorPos(@@g_Window, mouse_x, mouse_y)
|
106
|
+
io[:MousePos][:x] = mouse_x.unpack1('d')
|
107
|
+
io[:MousePos][:y] = mouse_y.unpack1('d')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.ImplGlfw_UpdateMouseCursor()
|
112
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
113
|
+
return if ((io[:ConfigFlags] & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(@@g_Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
|
114
|
+
|
115
|
+
imgui_cursor = ImGui::GetMouseCursor()
|
116
|
+
if imgui_cursor == ImGuiMouseCursor_None || io[:MouseDrawCursor]
|
117
|
+
# Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
118
|
+
glfwSetInputMode(@@g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN)
|
119
|
+
else
|
120
|
+
# Show OS mouse cursor
|
121
|
+
# FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
122
|
+
glfwSetCursor(@@g_Window, @@g_MouseCursors[imgui_cursor] ? @@g_MouseCursors[imgui_cursor] : @@g_MouseCursors[ImGuiMouseCursor_Arrow])
|
123
|
+
glfwSetInputMode(@@g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.ImplGlfw_InitForOpenGL(window, install_callbacks)
|
128
|
+
return ImplGlfw_Init(window, install_callbacks, :GlfwClientApi_OpenGL)
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.ImplGlfw_Shutdown()
|
132
|
+
ImGuiMouseCursor_COUNT.times do |cursor_n|
|
133
|
+
glfwDestroyCursor(@@g_MouseCursors[cursor_n])
|
134
|
+
@@g_MouseCursors[cursor_n] = nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.ImplGlfw_NewFrame()
|
139
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
140
|
+
unless io[:Fonts].IsBuilt()
|
141
|
+
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()."
|
142
|
+
end
|
143
|
+
|
144
|
+
# Setup display size (every frame to accommodate for window resizing)
|
145
|
+
w = ' ' * 4
|
146
|
+
h = ' ' * 4
|
147
|
+
display_w = ' ' * 4
|
148
|
+
display_h = ' ' * 4
|
149
|
+
glfwGetWindowSize(@@g_Window, w, h)
|
150
|
+
glfwGetFramebufferSize(@@g_Window, display_w, display_h)
|
151
|
+
|
152
|
+
w = w.unpack1('L')
|
153
|
+
h = h.unpack1('L')
|
154
|
+
io[:DisplaySize][:x] = w
|
155
|
+
io[:DisplaySize][:y] = h
|
156
|
+
|
157
|
+
if w > 0 && h > 0
|
158
|
+
io[:DisplayFramebufferScale][:x] = display_w.unpack1('L') / w
|
159
|
+
io[:DisplayFramebufferScale][:y] = display_h.unpack1('L') / h
|
160
|
+
end
|
161
|
+
|
162
|
+
# Setup time step
|
163
|
+
current_time = glfwGetTime()
|
164
|
+
io[:DeltaTime] = @@g_Time > 0.0 ? (current_time - @@g_Time).to_f : (1.0/60.0)
|
165
|
+
@@g_Time = current_time
|
166
|
+
|
167
|
+
ImplGlfw_UpdateMousePosAndButtons()
|
168
|
+
ImplGlfw_UpdateMouseCursor()
|
169
|
+
# TODO update gamepads
|
170
|
+
end
|
171
|
+
|
172
|
+
# private
|
173
|
+
|
174
|
+
def self.ImplGlfw_Init(window, install_callbacks, client_api)
|
175
|
+
@@g_Window = window
|
176
|
+
@@g_Time = 0.0
|
177
|
+
|
178
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
179
|
+
io[:BackendFlags] |= ImGuiBackendFlags_HasMouseCursors # We can honor GetMouseCursor() values (optional)
|
180
|
+
io[:BackendFlags] |= ImGuiBackendFlags_HasSetMousePos # We can honor io.WantSetMousePos requests (optional, rarely used)
|
181
|
+
io[:BackendPlatformName] = @@g_BackendPlatformName
|
182
|
+
|
183
|
+
# Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
|
184
|
+
io[:KeyMap][ImGuiKey_Tab] = GLFW_KEY_TAB
|
185
|
+
io[:KeyMap][ImGuiKey_LeftArrow] = GLFW_KEY_LEFT
|
186
|
+
io[:KeyMap][ImGuiKey_RightArrow] = GLFW_KEY_RIGHT
|
187
|
+
io[:KeyMap][ImGuiKey_UpArrow] = GLFW_KEY_UP
|
188
|
+
io[:KeyMap][ImGuiKey_DownArrow] = GLFW_KEY_DOWN
|
189
|
+
io[:KeyMap][ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP
|
190
|
+
io[:KeyMap][ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN
|
191
|
+
io[:KeyMap][ImGuiKey_Home] = GLFW_KEY_HOME
|
192
|
+
io[:KeyMap][ImGuiKey_End] = GLFW_KEY_END
|
193
|
+
io[:KeyMap][ImGuiKey_Insert] = GLFW_KEY_INSERT
|
194
|
+
io[:KeyMap][ImGuiKey_Delete] = GLFW_KEY_DELETE
|
195
|
+
io[:KeyMap][ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE
|
196
|
+
io[:KeyMap][ImGuiKey_Space] = GLFW_KEY_SPACE
|
197
|
+
io[:KeyMap][ImGuiKey_Enter] = GLFW_KEY_ENTER
|
198
|
+
io[:KeyMap][ImGuiKey_Escape] = GLFW_KEY_ESCAPE
|
199
|
+
io[:KeyMap][ImGuiKey_KeyPadEnter] = GLFW_KEY_KP_ENTER
|
200
|
+
io[:KeyMap][ImGuiKey_A] = GLFW_KEY_A
|
201
|
+
io[:KeyMap][ImGuiKey_C] = GLFW_KEY_C
|
202
|
+
io[:KeyMap][ImGuiKey_V] = GLFW_KEY_V
|
203
|
+
io[:KeyMap][ImGuiKey_X] = GLFW_KEY_X
|
204
|
+
io[:KeyMap][ImGuiKey_Y] = GLFW_KEY_Y
|
205
|
+
io[:KeyMap][ImGuiKey_Z] = GLFW_KEY_Z
|
206
|
+
|
207
|
+
# [TODO] Support ClipboardText & IME on Windows
|
208
|
+
# io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
|
209
|
+
# io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
|
210
|
+
# io.ClipboardUserData = g_Window;
|
211
|
+
# #if defined(_WIN32)
|
212
|
+
# io.ImeWindowHandle = (void*)glfwGetWin32Window(g_Window);
|
213
|
+
# #endif
|
214
|
+
|
215
|
+
@@g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR)
|
216
|
+
@@g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR)
|
217
|
+
@@g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR) # FIXME: GLFW doesn't have this.
|
218
|
+
@@g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR)
|
219
|
+
@@g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR)
|
220
|
+
@@g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR) # FIXME: GLFW doesn't have this.
|
221
|
+
@@g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR) # FIXME: GLFW doesn't have this.
|
222
|
+
@@g_MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR)
|
223
|
+
|
224
|
+
# Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
|
225
|
+
@@g_PrevUserCallbackMousebutton = nil
|
226
|
+
@@g_PrevUserCallbackScroll = nil
|
227
|
+
@@g_PrevUserCallbackKey = nil
|
228
|
+
@@g_PrevUserCallbackChar = nil
|
229
|
+
if install_callbacks
|
230
|
+
@@g_PrevUserCallbackCursorEnter = glfwSetCursorEnterCallback(window, @@ImGui_ImplGlfw_CursorEnterCallback)
|
231
|
+
@@g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, @@ImplGlfw_MouseButtonCallback)
|
232
|
+
@@g_PrevUserCallbackScroll = glfwSetScrollCallback(window, @@ImplGlfw_ScrollCallback)
|
233
|
+
@@g_PrevUserCallbackKey = glfwSetKeyCallback(window, @@ImplGlfw_KeyCallback)
|
234
|
+
@@g_PrevUserCallbackChar = glfwSetCharCallback(window, @@ImplGlfw_CharCallback)
|
235
|
+
end
|
236
|
+
|
237
|
+
return true
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'opengl'
|
3
|
+
include OpenGL
|
4
|
+
|
5
|
+
require_relative 'imgui'
|
6
|
+
|
7
|
+
module ImGui
|
8
|
+
|
9
|
+
@@g_FontTexture = nil
|
10
|
+
@@g_BackendRendererName = FFI::MemoryPointer.from_string("imgui_impl_opengl2")
|
11
|
+
|
12
|
+
def self.ImplOpenGL2_Init()
|
13
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
14
|
+
io[:BackendRendererName] = @@g_BackendRendererName
|
15
|
+
|
16
|
+
return true
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.ImplOpenGL2_Shutdown()
|
20
|
+
ImplOpenGL2_DestroyDeviceObjects()
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.ImplOpenGL2_NewFrame()
|
24
|
+
ImplOpenGL2_CreateDeviceObjects() if @@g_FontTexture == nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.ImplOpenGL2_RenderDrawData(draw_data_raw)
|
28
|
+
# Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
29
|
+
draw_data = ImDrawData.new(draw_data_raw)
|
30
|
+
fb_width = (draw_data[:DisplaySize][:x] * draw_data[:FramebufferScale][:x]).to_i
|
31
|
+
fb_height = (draw_data[:DisplaySize][:y] * draw_data[:FramebufferScale][:y]).to_i
|
32
|
+
|
33
|
+
return if fb_width == 0 || fb_height == 0
|
34
|
+
|
35
|
+
# Backup GL state
|
36
|
+
last_texture = ' ' * 4
|
37
|
+
glGetIntegerv(GL_TEXTURE_BINDING_2D, last_texture)
|
38
|
+
last_polygon_mode = ' ' * 8
|
39
|
+
glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode)
|
40
|
+
last_viewport = ' ' * 16
|
41
|
+
glGetIntegerv(GL_VIEWPORT, last_viewport)
|
42
|
+
last_scissor_box = ' ' * 16
|
43
|
+
glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box)
|
44
|
+
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT)
|
45
|
+
last_shade_model = ' ' * 4
|
46
|
+
glGetIntegerv(GL_SHADE_MODEL, last_shade_model)
|
47
|
+
last_tex_env_mode = ' ' * 4
|
48
|
+
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode)
|
49
|
+
|
50
|
+
# Setup desired GL state
|
51
|
+
ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height)
|
52
|
+
|
53
|
+
# Will project scissor/clipping rectangles into framebuffer space
|
54
|
+
clip_off = draw_data[:DisplayPos] # (0,0) unless using multi-viewports
|
55
|
+
clip_scale = draw_data[:FramebufferScale] # (1,1) unless using retina display which are often (2,2)
|
56
|
+
|
57
|
+
# Render command lists
|
58
|
+
draw_data[:CmdListsCount].times do |n|
|
59
|
+
cmd_list = ImDrawList.new((draw_data[:CmdLists].pointer + 8 * n).read_pointer) # 8 == const ImDrawList*
|
60
|
+
vtx_buffer = ImDrawVert.new(cmd_list[:VtxBuffer][:Data]) # const ImDrawVert*
|
61
|
+
idx_buffer = cmd_list[:IdxBuffer][:Data] # const ImDrawIdx*
|
62
|
+
glVertexPointer(2, GL_FLOAT, ImDrawVert.size, Fiddle::Pointer.new((cmd_list[:VtxBuffer][:Data] + vtx_buffer.offset_of(:pos))) )
|
63
|
+
glTexCoordPointer(2, GL_FLOAT, ImDrawVert.size, Fiddle::Pointer.new((cmd_list[:VtxBuffer][:Data] + vtx_buffer.offset_of(:uv))) )
|
64
|
+
glColorPointer(4, GL_UNSIGNED_BYTE, ImDrawVert.size, Fiddle::Pointer.new((cmd_list[:VtxBuffer][:Data] + vtx_buffer.offset_of(:col))) )
|
65
|
+
|
66
|
+
cmd_list[:CmdBuffer][:Size].times do |cmd_i|
|
67
|
+
pcmd = ImDrawCmd.new(cmd_list[:CmdBuffer][:Data] + ImDrawCmd.size * cmd_i) # const ImDrawCmd*
|
68
|
+
if pcmd[:UserCallback] != nil
|
69
|
+
# [TODO] Handle user callback (Ref.: https://github.com/ffi/ffi/wiki/Callbacks )
|
70
|
+
|
71
|
+
# User callback, registered via ImDrawList::AddCallback()
|
72
|
+
# (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
73
|
+
# if pcmd[:UserCallback] == :ImDrawCallback_ResetRenderState
|
74
|
+
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height)
|
75
|
+
# else
|
76
|
+
# pcmd[:UserCallback](cmd_list, pcmd)
|
77
|
+
# end
|
78
|
+
else
|
79
|
+
# Project scissor/clipping rectangles into framebuffer space
|
80
|
+
clip_rect = ImVec4.new
|
81
|
+
clip_rect[:x] = (pcmd[:ClipRect][:x] - clip_off[:x]) * clip_scale[:x]
|
82
|
+
clip_rect[:y] = (pcmd[:ClipRect][:y] - clip_off[:y]) * clip_scale[:y]
|
83
|
+
clip_rect[:z] = (pcmd[:ClipRect][:z] - clip_off[:x]) * clip_scale[:x]
|
84
|
+
clip_rect[:w] = (pcmd[:ClipRect][:w] - clip_off[:y]) * clip_scale[:y]
|
85
|
+
|
86
|
+
if (clip_rect[:x] < fb_width && clip_rect[:y] < fb_height && clip_rect[:z] >= 0.0 && clip_rect[:w] >= 0.0)
|
87
|
+
# Apply scissor/clipping rectangle
|
88
|
+
glScissor(clip_rect[:x].to_i, (fb_height - clip_rect[:w]).to_i, (clip_rect[:z] - clip_rect[:x]).to_i, (clip_rect[:w] - clip_rect[:y]).to_i)
|
89
|
+
|
90
|
+
# Bind texture, Draw
|
91
|
+
glBindTexture(GL_TEXTURE_2D, pcmd[:TextureId].address)
|
92
|
+
glDrawElements(GL_TRIANGLES, pcmd[:ElemCount], GL_UNSIGNED_SHORT, Fiddle::Pointer.new(idx_buffer.address))
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
idx_buffer += pcmd[:ElemCount] * 2 # 2 == ImDrawIdx(:ushort).size
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Restore modified GL state
|
101
|
+
glDisableClientState(GL_COLOR_ARRAY)
|
102
|
+
glDisableClientState(GL_TEXTURE_COORD_ARRAY)
|
103
|
+
glDisableClientState(GL_VERTEX_ARRAY)
|
104
|
+
glBindTexture(GL_TEXTURE_2D, last_texture.unpack1('L'))
|
105
|
+
glMatrixMode(GL_MODELVIEW)
|
106
|
+
glPopMatrix()
|
107
|
+
glMatrixMode(GL_PROJECTION)
|
108
|
+
glPopMatrix()
|
109
|
+
glPopAttrib()
|
110
|
+
last_polygon_mode = last_polygon_mode.unpack('L2')
|
111
|
+
glPolygonMode(GL_FRONT, last_polygon_mode[0])
|
112
|
+
glPolygonMode(GL_BACK, last_polygon_mode[1])
|
113
|
+
last_viewport = last_viewport.unpack('L4')
|
114
|
+
glViewport(last_viewport[0], last_viewport[1], last_viewport[2], last_viewport[3])
|
115
|
+
last_scissor_box = last_scissor_box.unpack('L4')
|
116
|
+
glScissor(last_scissor_box[0], last_scissor_box[1], last_scissor_box[2], last_scissor_box[3])
|
117
|
+
glShadeModel(last_shade_model.unpack1('L'))
|
118
|
+
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode.unpack1('L'))
|
119
|
+
end
|
120
|
+
|
121
|
+
# private
|
122
|
+
|
123
|
+
def self.ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height)
|
124
|
+
# Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
|
125
|
+
glEnable(GL_BLEND)
|
126
|
+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
127
|
+
# glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA) # In order to composite our output buffer we need to preserve alpha
|
128
|
+
glDisable(GL_CULL_FACE)
|
129
|
+
glDisable(GL_STENCIL_TEST)
|
130
|
+
glDisable(GL_DEPTH_TEST)
|
131
|
+
glDisable(GL_LIGHTING)
|
132
|
+
glDisable(GL_COLOR_MATERIAL)
|
133
|
+
glEnable(GL_SCISSOR_TEST)
|
134
|
+
glEnableClientState(GL_VERTEX_ARRAY)
|
135
|
+
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
136
|
+
glEnableClientState(GL_COLOR_ARRAY)
|
137
|
+
glDisableClientState(GL_NORMAL_ARRAY)
|
138
|
+
glEnable(GL_TEXTURE_2D)
|
139
|
+
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
|
140
|
+
glShadeModel(GL_SMOOTH)
|
141
|
+
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
|
142
|
+
|
143
|
+
# If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
|
144
|
+
# you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
|
145
|
+
# (DO NOT MODIFY THIS FILE! Add the code in your calling function)
|
146
|
+
# GLint last_program;
|
147
|
+
# glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
148
|
+
# glUseProgram(0);
|
149
|
+
# ImGui_ImplOpenGL2_RenderDrawData(...);
|
150
|
+
# glUseProgram(last_program)
|
151
|
+
# There are potentially many more states you could need to clear/setup that we can't access from default headers.
|
152
|
+
# e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP).
|
153
|
+
|
154
|
+
# Setup viewport, orthographic projection matrix
|
155
|
+
# Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
156
|
+
glViewport(0, 0, fb_width, fb_height)
|
157
|
+
glMatrixMode(GL_PROJECTION)
|
158
|
+
glPushMatrix()
|
159
|
+
glLoadIdentity()
|
160
|
+
glOrtho(draw_data[:DisplayPos][:x], draw_data[:DisplayPos][:x] + draw_data[:DisplaySize][:x], draw_data[:DisplayPos][:y] + draw_data[:DisplaySize][:y], draw_data[:DisplayPos][:y], -1.0, +1.0)
|
161
|
+
glMatrixMode(GL_MODELVIEW)
|
162
|
+
glPushMatrix()
|
163
|
+
glLoadIdentity()
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.ImplOpenGL2_CreateFontsTexture()
|
167
|
+
# Build texture atlas
|
168
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
169
|
+
pixels = FFI::MemoryPointer.new :pointer
|
170
|
+
width = FFI::MemoryPointer.new :int
|
171
|
+
height = FFI::MemoryPointer.new :int
|
172
|
+
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.
|
173
|
+
|
174
|
+
# Upload texture to graphics system
|
175
|
+
last_texture = ' ' * 4
|
176
|
+
@@g_FontTexture = ' ' * 4
|
177
|
+
glGetIntegerv(GL_TEXTURE_BINDING_2D, last_texture)
|
178
|
+
glGenTextures(1, @@g_FontTexture)
|
179
|
+
glBindTexture(GL_TEXTURE_2D, @@g_FontTexture.unpack1('L'))
|
180
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
181
|
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
182
|
+
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)
|
183
|
+
# Ruby/FFI <-> Fiddle pointer exchange
|
184
|
+
pixels_ptr = Fiddle::Pointer.new(pixels.read_pointer.address)
|
185
|
+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width.read_uint, height.read_uint, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels_ptr)
|
186
|
+
|
187
|
+
# Store our identifier
|
188
|
+
io[:Fonts][:TexID] = @@g_FontTexture.unpack1('L')
|
189
|
+
|
190
|
+
# Restore state
|
191
|
+
glBindTexture(GL_TEXTURE_2D, last_texture.unpack1('L'))
|
192
|
+
|
193
|
+
return true
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.ImplOpenGL2_DestroyFontsTexture()
|
197
|
+
if @@g_FontTexture != 0
|
198
|
+
glDeleteTextures(1, @@g_FontTexture)
|
199
|
+
io = ImGuiIO.new(ImGui::GetIO())
|
200
|
+
io[:Fonts][:TexID] = 0
|
201
|
+
@@g_FontTexture = 0
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def self.ImplOpenGL2_CreateDeviceObjects()
|
206
|
+
return ImplOpenGL2_CreateFontsTexture()
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.ImplOpenGL2_DestroyDeviceObjects()
|
210
|
+
ImplOpenGL2_DestroyFontsTexture()
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|