imgui-bindings 0.1.10-arm64-darwin

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,212 @@
1
+ require 'ffi'
2
+ require 'opengl'
3
+
4
+ require_relative 'imgui'
5
+
6
+ module ImGui
7
+
8
+ @@g_FontTexture = nil
9
+ @@g_BackendRendererName = FFI::MemoryPointer.from_string("imgui_impl_opengl2")
10
+
11
+ def self.ImplOpenGL2_Init()
12
+ io = ImGuiIO.new(ImGui::GetIO())
13
+ io[:BackendRendererName] = @@g_BackendRendererName
14
+
15
+ return true
16
+ end
17
+
18
+ def self.ImplOpenGL2_Shutdown()
19
+ ImplOpenGL2_DestroyDeviceObjects()
20
+ end
21
+
22
+ def self.ImplOpenGL2_NewFrame()
23
+ ImplOpenGL2_CreateDeviceObjects() if @@g_FontTexture == nil
24
+ end
25
+
26
+ def self.ImplOpenGL2_RenderDrawData(draw_data_raw)
27
+ # Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
28
+ draw_data = ImDrawData.new(draw_data_raw)
29
+ fb_width = (draw_data[:DisplaySize][:x] * draw_data[:FramebufferScale][:x]).to_i
30
+ fb_height = (draw_data[:DisplaySize][:y] * draw_data[:FramebufferScale][:y]).to_i
31
+
32
+ return if fb_width == 0 || fb_height == 0
33
+
34
+ # Backup GL state
35
+ last_texture = ' ' * 4
36
+ GL.GetIntegerv(GL::TEXTURE_BINDING_2D, last_texture)
37
+ last_polygon_mode = ' ' * 8
38
+ GL.GetIntegerv(GL::POLYGON_MODE, last_polygon_mode)
39
+ last_viewport = ' ' * 16
40
+ GL.GetIntegerv(GL::VIEWPORT, last_viewport)
41
+ last_scissor_box = ' ' * 16
42
+ GL.GetIntegerv(GL::SCISSOR_BOX, last_scissor_box)
43
+ GL.PushAttrib(GL::ENABLE_BIT | GL::COLOR_BUFFER_BIT | GL::TRANSFORM_BIT)
44
+ last_shade_model = ' ' * 4
45
+ GL.GetIntegerv(GL::SHADE_MODEL, last_shade_model)
46
+ last_tex_env_mode = ' ' * 4
47
+ GL.GetTexEnviv(GL::TEXTURE_ENV, GL::TEXTURE_ENV_MODE, last_tex_env_mode)
48
+
49
+ # Setup desired GL state
50
+ ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height)
51
+
52
+ # Will project scissor/clipping rectangles into framebuffer space
53
+ clip_off = draw_data[:DisplayPos] # (0,0) unless using multi-viewports
54
+ clip_scale = draw_data[:FramebufferScale] # (1,1) unless using retina display which are often (2,2)
55
+
56
+ # Render command lists
57
+ draw_data[:CmdListsCount].times do |n|
58
+ cmd_list = ImDrawList.new((draw_data[:CmdLists][:Data] + 8 * n).read_pointer) # 8 == const ImDrawList*
59
+ vtx_buffer = ImDrawVert.new(cmd_list[:VtxBuffer][:Data]) # const ImDrawVert*
60
+ idx_buffer = cmd_list[:IdxBuffer][:Data] # const ImDrawIdx*
61
+ GL.VertexPointer(2, GL::FLOAT, ImDrawVert.size, Fiddle::Pointer.new((cmd_list[:VtxBuffer][:Data] + vtx_buffer.offset_of(:pos))) )
62
+ GL.TexCoordPointer(2, GL::FLOAT, ImDrawVert.size, Fiddle::Pointer.new((cmd_list[:VtxBuffer][:Data] + vtx_buffer.offset_of(:uv))) )
63
+ GL.ColorPointer(4, GL::UNSIGNED_BYTE, ImDrawVert.size, Fiddle::Pointer.new((cmd_list[:VtxBuffer][:Data] + vtx_buffer.offset_of(:col))) )
64
+
65
+ cmd_list[:CmdBuffer][:Size].times do |cmd_i|
66
+ pcmd = ImDrawCmd.new(cmd_list[:CmdBuffer][:Data] + ImDrawCmd.size * cmd_i) # const ImDrawCmd*
67
+ if pcmd[:UserCallback] != nil
68
+ # [TODO] Handle user callback (Ref.: https://github.com/ffi/ffi/wiki/Callbacks )
69
+
70
+ # User callback, registered via ImDrawList::AddCallback()
71
+ # (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
72
+ # if pcmd[:UserCallback] == :ImDrawCallback_ResetRenderState
73
+ ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height)
74
+ # else
75
+ # pcmd[:UserCallback](cmd_list, pcmd)
76
+ # end
77
+ else
78
+ # Project scissor/clipping rectangles into framebuffer space
79
+ clip_rect = ImVec4.new
80
+ clip_rect[:x] = (pcmd[:ClipRect][:x] - clip_off[:x]) * clip_scale[:x]
81
+ clip_rect[:y] = (pcmd[:ClipRect][:y] - clip_off[:y]) * clip_scale[:y]
82
+ clip_rect[:z] = (pcmd[:ClipRect][:z] - clip_off[:x]) * clip_scale[:x]
83
+ clip_rect[:w] = (pcmd[:ClipRect][:w] - clip_off[:y]) * clip_scale[:y]
84
+
85
+ if (clip_rect[:x] < fb_width && clip_rect[:y] < fb_height && clip_rect[:z] >= 0.0 && clip_rect[:w] >= 0.0)
86
+ # Apply scissor/clipping rectangle
87
+ GL.Scissor(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)
88
+
89
+ # Bind texture, Draw
90
+ GL.BindTexture(GL::TEXTURE_2D, pcmd[:TextureId].address)
91
+ GL.DrawElements(GL::TRIANGLES, pcmd[:ElemCount], GL::UNSIGNED_SHORT, Fiddle::Pointer.new(idx_buffer.address))
92
+ end
93
+
94
+ end
95
+ idx_buffer += pcmd[:ElemCount] * 2 # 2 == ImDrawIdx(:ushort).size
96
+ end
97
+ end
98
+
99
+ # Restore modified GL state
100
+ GL.DisableClientState(GL::COLOR_ARRAY)
101
+ GL.DisableClientState(GL::TEXTURE_COORD_ARRAY)
102
+ GL.DisableClientState(GL::VERTEX_ARRAY)
103
+ GL.BindTexture(GL::TEXTURE_2D, last_texture.unpack1('L'))
104
+ GL.MatrixMode(GL::MODELVIEW)
105
+ GL.PopMatrix()
106
+ GL.MatrixMode(GL::PROJECTION)
107
+ GL.PopMatrix()
108
+ GL.PopAttrib()
109
+ last_polygon_mode = last_polygon_mode.unpack('L2')
110
+ GL.PolygonMode(GL::FRONT, last_polygon_mode[0])
111
+ GL.PolygonMode(GL::BACK, last_polygon_mode[1])
112
+ last_viewport = last_viewport.unpack('L4')
113
+ GL.Viewport(last_viewport[0], last_viewport[1], last_viewport[2], last_viewport[3])
114
+ last_scissor_box = last_scissor_box.unpack('L4')
115
+ GL.Scissor(last_scissor_box[0], last_scissor_box[1], last_scissor_box[2], last_scissor_box[3])
116
+ GL.ShadeModel(last_shade_model.unpack1('L'))
117
+ GL.TexEnvi(GL::TEXTURE_ENV, GL::TEXTURE_ENV_MODE, last_tex_env_mode.unpack1('L'))
118
+ end
119
+
120
+ # private
121
+
122
+ def self.ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height)
123
+ # Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
124
+ GL.Enable(GL::BLEND)
125
+ GL.BlendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA)
126
+ # GL.BlendFuncSeparate(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
127
+ GL.Disable(GL::CULL_FACE)
128
+ GL.Disable(GL::STENCIL_TEST)
129
+ GL.Disable(GL::DEPTH_TEST)
130
+ GL.Disable(GL::LIGHTING)
131
+ GL.Disable(GL::COLOR_MATERIAL)
132
+ GL.Enable(GL::SCISSOR_TEST)
133
+ GL.EnableClientState(GL::VERTEX_ARRAY)
134
+ GL.EnableClientState(GL::TEXTURE_COORD_ARRAY)
135
+ GL.EnableClientState(GL::COLOR_ARRAY)
136
+ GL.DisableClientState(GL::NORMAL_ARRAY)
137
+ GL.Enable(GL::TEXTURE_2D)
138
+ GL.PolygonMode(GL::FRONT_AND_BACK, GL::FILL)
139
+ GL.ShadeModel(GL::SMOOTH)
140
+ GL.TexEnvi(GL::TEXTURE_ENV, GL::TEXTURE_ENV_MODE, GL::MODULATE)
141
+
142
+ # If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
143
+ # you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
144
+ # (DO NOT MODIFY THIS FILE! Add the code in your calling function)
145
+ # GLint last_program;
146
+ # glGetIntegerv(GL::CURRENT_PROGRAM, &last_program);
147
+ # glUseProgram(0);
148
+ # ImGui_ImplOpenGL2_RenderDrawData(...);
149
+ # glUseProgram(last_program)
150
+ # There are potentially many more states you could need to clear/setup that we can't access from default headers.
151
+ # e.g. glBindBuffer(GL::ARRAY_BUFFER, 0), glDisable(GL::TEXTURE_CUBE_MAP).
152
+
153
+ # Setup viewport, orthographic projection matrix
154
+ # 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.
155
+ GL.Viewport(0, 0, fb_width, fb_height)
156
+ GL.MatrixMode(GL::PROJECTION)
157
+ GL.PushMatrix()
158
+ GL.LoadIdentity()
159
+ GL.Ortho(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)
160
+ GL.MatrixMode(GL::MODELVIEW)
161
+ GL.PushMatrix()
162
+ GL.LoadIdentity()
163
+ end
164
+
165
+ def self.ImplOpenGL2_CreateFontsTexture()
166
+ # Build texture atlas
167
+ io = ImGuiIO.new(ImGui::GetIO())
168
+ pixels = FFI::MemoryPointer.new :pointer
169
+ width = FFI::MemoryPointer.new :int
170
+ height = FFI::MemoryPointer.new :int
171
+ 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.
172
+
173
+ # Upload texture to graphics system
174
+ last_texture = ' ' * 4
175
+ @@g_FontTexture = ' ' * 4
176
+ GL.GetIntegerv(GL::TEXTURE_BINDING_2D, last_texture)
177
+ GL.GenTextures(1, @@g_FontTexture)
178
+ GL.BindTexture(GL::TEXTURE_2D, @@g_FontTexture.unpack1('L'))
179
+ GL.TexParameteri(GL::TEXTURE_2D, GL::TEXTURE_MIN_FILTER, GL::LINEAR)
180
+ GL.TexParameteri(GL::TEXTURE_2D, GL::TEXTURE_MAG_FILTER, GL::LINEAR)
181
+ GL.PixelStorei(GL::UNPACK_ROW_LENGTH, 0)
182
+ # Ruby/FFI <-> Fiddle pointer exchange
183
+ pixels_ptr = Fiddle::Pointer.new(pixels.read_pointer.address)
184
+ GL.TexImage2D(GL::TEXTURE_2D, 0, GL::RGBA, width.read_uint, height.read_uint, 0, GL::RGBA, GL::UNSIGNED_BYTE, pixels_ptr)
185
+
186
+ # Store our identifier
187
+ io[:Fonts][:TexID] = @@g_FontTexture.unpack1('L')
188
+
189
+ # Restore state
190
+ GL.BindTexture(GL::TEXTURE_2D, last_texture.unpack1('L'))
191
+
192
+ return true
193
+ end
194
+
195
+ def self.ImplOpenGL2_DestroyFontsTexture()
196
+ if @@g_FontTexture != 0
197
+ GL.DeleteTextures(1, @@g_FontTexture)
198
+ io = ImGuiIO.new(ImGui::GetIO())
199
+ io[:Fonts][:TexID] = 0
200
+ @@g_FontTexture = 0
201
+ end
202
+ end
203
+
204
+ def self.ImplOpenGL2_CreateDeviceObjects()
205
+ return ImplOpenGL2_CreateFontsTexture()
206
+ end
207
+
208
+ def self.ImplOpenGL2_DestroyDeviceObjects()
209
+ ImplOpenGL2_DestroyFontsTexture()
210
+ end
211
+
212
+ end