imgui 1.0.0
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/LICENSE.txt +21 -0
- data/README.md +273 -0
- data/Rakefile +97 -0
- data/api/v1.json +53 -0
- data/ext/CMakeLists.txt +128 -0
- data/ext/Rakefile +31 -0
- data/ext/backend_function_bridge.cpp +180 -0
- data/ext/backend_function_bridge.h +40 -0
- data/ext/build_cimgui.rb +59 -0
- data/ext/extconf.rb +25 -0
- data/ext/glfw_vulkan_bridge.cpp +14 -0
- data/ext/imgui_ruby_build_config.h +17 -0
- data/ext/imgui_ruby_glfw.cpp +73 -0
- data/ext/imgui_ruby_sdl3.cpp +70 -0
- data/ext/imgui_ruby_wgpu.cpp +75 -0
- data/ext/install_cimgui.rb +25 -0
- data/ext/webgpu_function_bridge.cpp +245 -0
- data/generator/api_emitter.rb +164 -0
- data/generator/emitter.rb +317 -0
- data/generator/generate.rb +47 -0
- data/generator/native-dependencies.yml +88 -0
- data/generator/native_dependency_lock.rb +78 -0
- data/generator/native_dependency_snapshot.rb +159 -0
- data/generator/overrides.yml +11 -0
- data/generator/type_mapper.rb +112 -0
- data/generator/update_vendor.rb +30 -0
- data/lib/imgui/api.rb +88 -0
- data/lib/imgui/api_generated.rb +1633 -0
- data/lib/imgui/api_support.rb +144 -0
- data/lib/imgui/backends/glfw.rb +75 -0
- data/lib/imgui/backends/opengl3.rb +44 -0
- data/lib/imgui/backends/sdl3.rb +133 -0
- data/lib/imgui/backends/wgpu.rb +176 -0
- data/lib/imgui/backends.rb +60 -0
- data/lib/imgui/draw_data.rb +43 -0
- data/lib/imgui/dsl.rb +311 -0
- data/lib/imgui/dsl_support.rb +107 -0
- data/lib/imgui/easy_loop.rb +25 -0
- data/lib/imgui/errors.rb +11 -0
- data/lib/imgui/fonts.rb +46 -0
- data/lib/imgui/io.rb +91 -0
- data/lib/imgui/layout.rb +138 -0
- data/lib/imgui/memory_pool.rb +18 -0
- data/lib/imgui/native/enums.rb +2251 -0
- data/lib/imgui/native/functions.rb +1470 -0
- data/lib/imgui/native/structs.rb +1926 -0
- data/lib/imgui/native/typedefs.rb +93 -0
- data/lib/imgui/native.rb +130 -0
- data/lib/imgui/plot/api.rb +273 -0
- data/lib/imgui/plot/native/enums.rb +593 -0
- data/lib/imgui/plot/native/functions.rb +749 -0
- data/lib/imgui/plot/native/structs.rb +363 -0
- data/lib/imgui/plot/native/typedefs.rb +79 -0
- data/lib/imgui/plot.rb +13 -0
- data/lib/imgui/struct_value.rb +33 -0
- data/lib/imgui/style.rb +44 -0
- data/lib/imgui/value.rb +104 -0
- data/lib/imgui/version.rb +5 -0
- data/lib/imgui/widgets.rb +187 -0
- data/lib/imgui.rb +30 -0
- data/rakelib/platform_gem.rake +54 -0
- data/rakelib/source_gem.rake +75 -0
- metadata +129 -0
data/lib/imgui/dsl.rb
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ImGui
|
|
4
|
+
class << self
|
|
5
|
+
def window(title, open: nil, flags: 0, &block)
|
|
6
|
+
guard_context!
|
|
7
|
+
open_pointer = boolean_pointer(open)
|
|
8
|
+
run_scope(
|
|
9
|
+
:window,
|
|
10
|
+
:igEnd,
|
|
11
|
+
Native.igBegin(title.to_s, open_pointer, Integer(flags)),
|
|
12
|
+
always_close: true,
|
|
13
|
+
&block
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def child(id, size: [0, 0], child_flags: 0, window_flags: 0, &block)
|
|
18
|
+
guard_context!
|
|
19
|
+
opened = Native.igBeginChild_Str(
|
|
20
|
+
id.to_s,
|
|
21
|
+
StructValue.vec2(size),
|
|
22
|
+
Integer(child_flags),
|
|
23
|
+
Integer(window_flags)
|
|
24
|
+
)
|
|
25
|
+
run_scope(:child, :igEndChild, opened, always_close: true, &block)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def child_id(id, size: [0, 0], child_flags: 0, window_flags: 0, &block)
|
|
29
|
+
guard_context!
|
|
30
|
+
opened = Native.igBeginChild_ID(
|
|
31
|
+
Integer(id),
|
|
32
|
+
StructValue.vec2(size),
|
|
33
|
+
Integer(child_flags),
|
|
34
|
+
Integer(window_flags)
|
|
35
|
+
)
|
|
36
|
+
run_scope(:child, :igEndChild, opened, always_close: true, &block)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def menu_bar(&block)
|
|
40
|
+
conditional_scope(:menu_bar, :igBeginMenuBar, :igEndMenuBar, &block)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def main_menu_bar(&block)
|
|
44
|
+
conditional_scope(:main_menu_bar, :igBeginMainMenuBar, :igEndMainMenuBar, &block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def menu(label, enabled: true, &block)
|
|
48
|
+
conditional_scope(:menu, :igBeginMenu, :igEndMenu, label.to_s, !!enabled, &block)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def popup(id, flags: 0, &block)
|
|
52
|
+
conditional_scope(:popup, :igBeginPopup, :igEndPopup, id.to_s, Integer(flags), &block)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def popup_context_item(id = nil, flags: PopupFlags::MouseButtonRight, &block)
|
|
56
|
+
conditional_scope(
|
|
57
|
+
:popup,
|
|
58
|
+
:igBeginPopupContextItem,
|
|
59
|
+
:igEndPopup,
|
|
60
|
+
id&.to_s,
|
|
61
|
+
Integer(flags),
|
|
62
|
+
&block
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def popup_context_window(id = nil, flags: PopupFlags::MouseButtonRight, &block)
|
|
67
|
+
conditional_scope(
|
|
68
|
+
:popup,
|
|
69
|
+
:igBeginPopupContextWindow,
|
|
70
|
+
:igEndPopup,
|
|
71
|
+
id&.to_s,
|
|
72
|
+
Integer(flags),
|
|
73
|
+
&block
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def popup_context_void(id = nil, flags: PopupFlags::MouseButtonRight, &block)
|
|
78
|
+
conditional_scope(
|
|
79
|
+
:popup,
|
|
80
|
+
:igBeginPopupContextVoid,
|
|
81
|
+
:igEndPopup,
|
|
82
|
+
id&.to_s,
|
|
83
|
+
Integer(flags),
|
|
84
|
+
&block
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def popup_modal(title, open: nil, flags: 0, &block)
|
|
89
|
+
conditional_scope(
|
|
90
|
+
:popup,
|
|
91
|
+
:igBeginPopupModal,
|
|
92
|
+
:igEndPopup,
|
|
93
|
+
title.to_s,
|
|
94
|
+
boolean_pointer(open),
|
|
95
|
+
Integer(flags),
|
|
96
|
+
&block
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def combo(label, preview = nil, flags: 0, &block)
|
|
101
|
+
conditional_scope(:combo, :igBeginCombo, :igEndCombo, label.to_s, preview, Integer(flags), &block)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def combo_preview(&block)
|
|
105
|
+
conditional_scope(:combo_preview, :igBeginComboPreview, :igEndComboPreview, &block)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def list_box(label, size: [0, 0], &block)
|
|
109
|
+
conditional_scope(
|
|
110
|
+
:list_box,
|
|
111
|
+
:igBeginListBox,
|
|
112
|
+
:igEndListBox,
|
|
113
|
+
label.to_s,
|
|
114
|
+
StructValue.vec2(size),
|
|
115
|
+
&block
|
|
116
|
+
)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def table(id, columns, flags: 0, outer_size: [0, 0], inner_width: 0.0, &block)
|
|
120
|
+
conditional_scope(
|
|
121
|
+
:table,
|
|
122
|
+
:igBeginTable,
|
|
123
|
+
:igEndTable,
|
|
124
|
+
id.to_s,
|
|
125
|
+
Integer(columns),
|
|
126
|
+
Integer(flags),
|
|
127
|
+
StructValue.vec2(outer_size),
|
|
128
|
+
Float(inner_width),
|
|
129
|
+
&block
|
|
130
|
+
)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def tab_bar(id, flags: 0, &block)
|
|
134
|
+
conditional_scope(:tab_bar, :igBeginTabBar, :igEndTabBar, id.to_s, Integer(flags), &block)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def tab_item(label, open: nil, flags: 0, &block)
|
|
138
|
+
conditional_scope(
|
|
139
|
+
:tab_item,
|
|
140
|
+
:igBeginTabItem,
|
|
141
|
+
:igEndTabItem,
|
|
142
|
+
label.to_s,
|
|
143
|
+
boolean_pointer(open),
|
|
144
|
+
Integer(flags),
|
|
145
|
+
&block
|
|
146
|
+
)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def tooltip(&block)
|
|
150
|
+
conditional_scope(:tooltip, :igBeginTooltip, :igEndTooltip, &block)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def item_tooltip(&block)
|
|
154
|
+
conditional_scope(:tooltip, :igBeginItemTooltip, :igEndTooltip, &block)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def multi_select(flags: 0, selection_size: 0, items_count: -1, &block)
|
|
158
|
+
pointer_scope(
|
|
159
|
+
:multi_select,
|
|
160
|
+
:igBeginMultiSelect,
|
|
161
|
+
:igEndMultiSelect,
|
|
162
|
+
Integer(flags),
|
|
163
|
+
Integer(selection_size),
|
|
164
|
+
Integer(items_count),
|
|
165
|
+
&block
|
|
166
|
+
)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def tree_node(label, &block)
|
|
170
|
+
conditional_scope(:tree_node, :igTreeNode_Str, :igTreePop, label.to_s, &block)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def tree_node_ex(label, flags: 0, &block)
|
|
174
|
+
conditional_scope(:tree_node, :igTreeNodeEx_Str, :igTreePop, label.to_s, Integer(flags), &block)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def drag_drop_source(flags: 0, &block)
|
|
178
|
+
conditional_scope(
|
|
179
|
+
:drag_drop_source,
|
|
180
|
+
:igBeginDragDropSource,
|
|
181
|
+
:igEndDragDropSource,
|
|
182
|
+
Integer(flags),
|
|
183
|
+
&block
|
|
184
|
+
)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def drag_drop_target(&block)
|
|
188
|
+
conditional_scope(:drag_drop_target, :igBeginDragDropTarget, :igEndDragDropTarget, &block)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def group(&block)
|
|
192
|
+
void_scope(:group, :igBeginGroup, :igEndGroup, &block)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def disabled(disabled = true, &block)
|
|
196
|
+
void_scope(:disabled, :igBeginDisabled, :igEndDisabled, !!disabled, &block)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def font(font, &block)
|
|
200
|
+
push_scope(:font, :igPushFont, :igPopFont, Backends.pointer(font), &block)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def item_width(width, &block)
|
|
204
|
+
push_scope(:item_width, :igPushItemWidth, :igPopItemWidth, Float(width), &block)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def text_wrap_pos(position = 0.0, &block)
|
|
208
|
+
push_scope(:text_wrap_pos, :igPushTextWrapPos, :igPopTextWrapPos, Float(position), &block)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def item_flag(flag, enabled = true, &block)
|
|
212
|
+
push_scope(:item_flag, :igPushItemFlag, :igPopItemFlag, Integer(flag), !!enabled, &block)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def focus_scope(id, &block)
|
|
216
|
+
push_scope(:focus_scope, :igPushFocusScope, :igPopFocusScope, Integer(id), &block)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def clip_rect(minimum, maximum, intersect: false, &block)
|
|
220
|
+
push_scope(
|
|
221
|
+
:clip_rect,
|
|
222
|
+
:igPushClipRect,
|
|
223
|
+
:igPopClipRect,
|
|
224
|
+
StructValue.vec2(minimum),
|
|
225
|
+
StructValue.vec2(maximum),
|
|
226
|
+
!!intersect,
|
|
227
|
+
&block
|
|
228
|
+
)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def style_color(index, color)
|
|
232
|
+
arguments = [
|
|
233
|
+
:style_color,
|
|
234
|
+
:igPushStyleColor_Vec4,
|
|
235
|
+
:igPopStyleColor,
|
|
236
|
+
Integer(index),
|
|
237
|
+
StructValue.vec4(color)
|
|
238
|
+
]
|
|
239
|
+
return push_scope(*arguments, pop_arguments: [1]) unless block_given?
|
|
240
|
+
|
|
241
|
+
push_scope(*arguments, pop_arguments: [1]) { yield }
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def style_var(index, value)
|
|
245
|
+
function, native_value = if value.is_a?(Array)
|
|
246
|
+
[:igPushStyleVar_Vec2, StructValue.vec2(value)]
|
|
247
|
+
else
|
|
248
|
+
[:igPushStyleVar_Float, Float(value)]
|
|
249
|
+
end
|
|
250
|
+
arguments = [:style_var, function, :igPopStyleVar, Integer(index), native_value]
|
|
251
|
+
return push_scope(*arguments, pop_arguments: [1]) unless block_given?
|
|
252
|
+
|
|
253
|
+
push_scope(*arguments, pop_arguments: [1]) { yield }
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def with_id(value)
|
|
257
|
+
guard_context!
|
|
258
|
+
push_id(value)
|
|
259
|
+
return run_pushed_scope(:id, :igPopID) unless block_given?
|
|
260
|
+
|
|
261
|
+
run_pushed_scope(:id, :igPopID) { yield }
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def end_window
|
|
265
|
+
close_manual_scope(:window)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def end_child
|
|
269
|
+
close_manual_scope(:child)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
{
|
|
273
|
+
end_menu_bar: :menu_bar,
|
|
274
|
+
end_main_menu_bar: :main_menu_bar,
|
|
275
|
+
end_menu: :menu,
|
|
276
|
+
end_popup: :popup,
|
|
277
|
+
end_combo: :combo,
|
|
278
|
+
end_combo_preview: :combo_preview,
|
|
279
|
+
end_list_box: :list_box,
|
|
280
|
+
end_table: :table,
|
|
281
|
+
end_tab_bar: :tab_bar,
|
|
282
|
+
end_tab_item: :tab_item,
|
|
283
|
+
end_tooltip: :tooltip,
|
|
284
|
+
end_multi_select: :multi_select,
|
|
285
|
+
tree_pop: :tree_node,
|
|
286
|
+
end_drag_drop_source: :drag_drop_source,
|
|
287
|
+
end_drag_drop_target: :drag_drop_target,
|
|
288
|
+
end_group: :group,
|
|
289
|
+
end_disabled: :disabled,
|
|
290
|
+
pop_font: :font,
|
|
291
|
+
pop_item_width: :item_width,
|
|
292
|
+
pop_text_wrap_pos: :text_wrap_pos,
|
|
293
|
+
pop_item_flag: :item_flag,
|
|
294
|
+
pop_focus_scope: :focus_scope,
|
|
295
|
+
pop_clip_rect: :clip_rect,
|
|
296
|
+
pop_style_color: :style_color,
|
|
297
|
+
pop_style_var: :style_var,
|
|
298
|
+
pop_id: :id
|
|
299
|
+
}.each do |method_name, kind|
|
|
300
|
+
define_method(method_name) { close_manual_scope(kind) }
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def close_scope
|
|
304
|
+
scope = scope_stack.last
|
|
305
|
+
raise StackError, "there is no open manual scope" unless scope
|
|
306
|
+
|
|
307
|
+
close_manual_scope(scope.fetch(0))
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
end
|
|
311
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ImGui
|
|
4
|
+
class << self
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def conditional_scope(kind, begin_function, end_function, *arguments, &block)
|
|
8
|
+
guard_context!
|
|
9
|
+
opened = Native.public_send(begin_function, *arguments)
|
|
10
|
+
run_scope(kind, end_function, opened, always_close: false, &block)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def void_scope(kind, begin_function, end_function, *arguments, &block)
|
|
14
|
+
guard_context!
|
|
15
|
+
Native.public_send(begin_function, *arguments)
|
|
16
|
+
run_scope(kind, end_function, true, always_close: true, &block)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def pointer_scope(kind, begin_function, end_function, *arguments, &block)
|
|
20
|
+
guard_context!
|
|
21
|
+
pointer = Native.public_send(begin_function, *arguments)
|
|
22
|
+
opened = !null_pointer?(pointer)
|
|
23
|
+
return run_scope(kind, end_function, pointer, always_close: false) unless block
|
|
24
|
+
return unless opened
|
|
25
|
+
|
|
26
|
+
begin
|
|
27
|
+
block.call(pointer)
|
|
28
|
+
ensure
|
|
29
|
+
Native.public_send(end_function)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def push_scope(kind, push_function, pop_function, *arguments, pop_arguments: [], &block)
|
|
34
|
+
guard_context!
|
|
35
|
+
Native.public_send(push_function, *arguments)
|
|
36
|
+
run_pushed_scope(kind, pop_function, *pop_arguments, &block)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def run_pushed_scope(kind, pop_function, *pop_arguments, &block)
|
|
40
|
+
unless block
|
|
41
|
+
scope_stack << [kind, pop_function, pop_arguments]
|
|
42
|
+
return true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
block.call
|
|
46
|
+
ensure
|
|
47
|
+
Native.public_send(pop_function, *pop_arguments) if block
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def run_scope(kind, end_function, opened, always_close:, &block)
|
|
51
|
+
should_close = always_close || opened
|
|
52
|
+
unless block
|
|
53
|
+
scope_stack << [kind, end_function] if should_close
|
|
54
|
+
return opened
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
return false unless should_close
|
|
58
|
+
|
|
59
|
+
begin
|
|
60
|
+
opened ? block.call : false
|
|
61
|
+
ensure
|
|
62
|
+
Native.public_send(end_function)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def close_manual_scope(expected_kind)
|
|
67
|
+
guard_context!
|
|
68
|
+
scope = scope_stack.pop
|
|
69
|
+
unless scope&.fetch(0) == expected_kind
|
|
70
|
+
scope_stack << scope if scope
|
|
71
|
+
actual = scope&.fetch(0) || "none"
|
|
72
|
+
raise StackError, "expected #{expected_kind} scope, found #{actual}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
Native.public_send(scope.fetch(1), *Array(scope[2]))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def scope_stack
|
|
79
|
+
Thread.current.thread_variable_get(:imgui_ruby_scope_stack) || begin
|
|
80
|
+
stack = []
|
|
81
|
+
Thread.current.thread_variable_set(:imgui_ruby_scope_stack, stack)
|
|
82
|
+
stack
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def boolean_pointer(value)
|
|
87
|
+
return nil if value.nil?
|
|
88
|
+
if value.is_a?(Value)
|
|
89
|
+
require_value_type!(value, :bool)
|
|
90
|
+
return value.pointer
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
pointer = MemoryPool.pointer(:bool)
|
|
94
|
+
pointer.put(:bool, 0, !!value)
|
|
95
|
+
pointer
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def push_id(value)
|
|
99
|
+
case value
|
|
100
|
+
when String then Native.igPushID_Str(value)
|
|
101
|
+
when Integer then Native.igPushID_Int(value)
|
|
102
|
+
when FFI::Pointer then Native.igPushID_Ptr(value)
|
|
103
|
+
else Native.igPushID_Ptr(FFI::Pointer.new(value.object_id))
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ImGui
|
|
4
|
+
class << self
|
|
5
|
+
def frame(platform: Backends::Glfw, renderer: Backends::OpenGL3)
|
|
6
|
+
renderer.new_frame
|
|
7
|
+
platform.new_frame
|
|
8
|
+
new_frame
|
|
9
|
+
result = yield
|
|
10
|
+
render
|
|
11
|
+
renderer.render_draw_data(draw_data)
|
|
12
|
+
result
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def easy_loop(window, platform: Backends::Glfw, renderer: Backends::OpenGL3)
|
|
16
|
+
raise ArgumentError, "a UI block is required" unless block_given?
|
|
17
|
+
|
|
18
|
+
until window.should_close?
|
|
19
|
+
::GLFW.poll_events if defined?(::GLFW) && ::GLFW.respond_to?(:poll_events)
|
|
20
|
+
frame(platform: platform, renderer: renderer) { yield }
|
|
21
|
+
window.swap_buffers if window.respond_to?(:swap_buffers)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/imgui/errors.rb
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ImGui
|
|
4
|
+
class Error < StandardError; end
|
|
5
|
+
class LibraryLoadError < Error; end
|
|
6
|
+
class MissingSymbolError < Error; end
|
|
7
|
+
class BackendUnavailableError < Error; end
|
|
8
|
+
class NoContextError < Error; end
|
|
9
|
+
class ThreadError < Error; end
|
|
10
|
+
class StackError < Error; end
|
|
11
|
+
end
|
data/lib/imgui/fonts.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ImGui
|
|
4
|
+
class Fonts
|
|
5
|
+
attr_reader :pointer
|
|
6
|
+
|
|
7
|
+
def initialize(pointer)
|
|
8
|
+
@pointer = pointer
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def add_font_default
|
|
12
|
+
ImGui.__send__(:guard_context!)
|
|
13
|
+
Native.ImFontAtlas_AddFontDefault(pointer, nil)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def add_font(path, size:, glyph_ranges: nil, merge: false)
|
|
17
|
+
ImGui.__send__(:guard_context!)
|
|
18
|
+
config = merge ? Native.ImFontConfig_ImFontConfig : nil
|
|
19
|
+
Native::ImFontConfig.new(config)[:MergeMode] = true if config
|
|
20
|
+
Native.ImFontAtlas_AddFontFromFileTTF(
|
|
21
|
+
pointer,
|
|
22
|
+
File.expand_path(path),
|
|
23
|
+
Float(size),
|
|
24
|
+
config,
|
|
25
|
+
glyph_ranges
|
|
26
|
+
)
|
|
27
|
+
ensure
|
|
28
|
+
Native.ImFontConfig_destroy(config) if config
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def add_font_jp(path, size:, merge: false)
|
|
32
|
+
ranges = Native.ImFontAtlas_GetGlyphRangesJapanese(pointer)
|
|
33
|
+
add_font(path, size: size, glyph_ranges: ranges, merge: merge)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def build
|
|
37
|
+
ImGui.__send__(:guard_context!)
|
|
38
|
+
Native.ImFontAtlas_Build(pointer)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def clear
|
|
42
|
+
ImGui.__send__(:guard_context!)
|
|
43
|
+
Native.ImFontAtlas_Clear(pointer)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/imgui/io.rb
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ImGui
|
|
4
|
+
class IO
|
|
5
|
+
BOOLEAN_FIELDS = %i[
|
|
6
|
+
want_capture_mouse want_capture_keyboard want_text_input want_set_mouse_pos
|
|
7
|
+
want_save_ini_settings nav_active nav_visible mouse_draw_cursor
|
|
8
|
+
].freeze
|
|
9
|
+
INTEGER_FIELDS = %i[config_flags backend_flags metrics_render_vertices metrics_render_indices].freeze
|
|
10
|
+
FLOAT_FIELDS = %i[delta_time framerate font_global_scale].freeze
|
|
11
|
+
|
|
12
|
+
attr_reader :pointer
|
|
13
|
+
|
|
14
|
+
def initialize(pointer)
|
|
15
|
+
@pointer = pointer
|
|
16
|
+
@native = Native::ImGuiIO.new(pointer)
|
|
17
|
+
@retained_strings = {}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
INTEGER_FIELDS.each do |field|
|
|
21
|
+
native_field = field.to_s.split("_").map(&:capitalize).join.to_sym
|
|
22
|
+
define_method(field) { @native[native_field] }
|
|
23
|
+
define_method("#{field}=") { |value| @native[native_field] = Integer(value) }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
FLOAT_FIELDS.each do |field|
|
|
27
|
+
native_field = field.to_s.split("_").map(&:capitalize).join.to_sym
|
|
28
|
+
define_method(field) { @native[native_field] }
|
|
29
|
+
define_method("#{field}=") { |value| @native[native_field] = Float(value) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
BOOLEAN_FIELDS.each do |field|
|
|
33
|
+
native_field = field.to_s.split("_").map(&:capitalize).join.to_sym
|
|
34
|
+
define_method(field) { @native[native_field] }
|
|
35
|
+
define_method("#{field}=") { |value| @native[native_field] = !!value }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def display_size
|
|
39
|
+
StructValue.to_a(@native[:DisplaySize], 2)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def display_size=(value)
|
|
43
|
+
@native[:DisplaySize] = StructValue.vec2(value)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def display_framebuffer_scale
|
|
47
|
+
StructValue.to_a(@native[:DisplayFramebufferScale], 2)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def display_framebuffer_scale=(value)
|
|
51
|
+
@native[:DisplayFramebufferScale] = StructValue.vec2(value)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def fonts
|
|
55
|
+
@fonts ||= Fonts.new(@native[:Fonts])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def ini_filename
|
|
59
|
+
pointer = @native[:IniFilename]
|
|
60
|
+
pointer.null? ? nil : pointer.read_string
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def ini_filename=(filename)
|
|
64
|
+
set_retained_string(:IniFilename, filename)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def log_filename
|
|
68
|
+
pointer = @native[:LogFilename]
|
|
69
|
+
pointer.null? ? nil : pointer.read_string
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def log_filename=(filename)
|
|
73
|
+
set_retained_string(:LogFilename, filename)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def set_retained_string(field, value)
|
|
79
|
+
if value.nil?
|
|
80
|
+
@retained_strings.delete(field)
|
|
81
|
+
@native[field] = nil
|
|
82
|
+
return nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
memory = FFI::MemoryPointer.from_string(String(value).encode(Encoding::UTF_8))
|
|
86
|
+
@retained_strings[field] = memory
|
|
87
|
+
@native[field] = memory
|
|
88
|
+
value
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|