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
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#include <webgpu/webgpu.h>
|
|
2
|
+
|
|
3
|
+
#include <cstring>
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
#if defined(_WIN32)
|
|
7
|
+
#define IMGUI_RUBY_EXPORT __declspec(dllexport)
|
|
8
|
+
#else
|
|
9
|
+
#define IMGUI_RUBY_EXPORT __attribute__((visibility("default")))
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
#define WGPU_FUNCTIONS(X) \
|
|
13
|
+
X(wgpuBindGroupLayoutRelease, WGPUProcBindGroupLayoutRelease) \
|
|
14
|
+
X(wgpuBindGroupRelease, WGPUProcBindGroupRelease) \
|
|
15
|
+
X(wgpuBufferDestroy, WGPUProcBufferDestroy) \
|
|
16
|
+
X(wgpuBufferRelease, WGPUProcBufferRelease) \
|
|
17
|
+
X(wgpuCommandEncoderBeginRenderPass, WGPUProcCommandEncoderBeginRenderPass) \
|
|
18
|
+
X(wgpuDeviceCreateBindGroup, WGPUProcDeviceCreateBindGroup) \
|
|
19
|
+
X(wgpuDeviceCreateBindGroupLayout, WGPUProcDeviceCreateBindGroupLayout) \
|
|
20
|
+
X(wgpuDeviceCreateBuffer, WGPUProcDeviceCreateBuffer) \
|
|
21
|
+
X(wgpuDeviceCreatePipelineLayout, WGPUProcDeviceCreatePipelineLayout) \
|
|
22
|
+
X(wgpuDeviceCreateRenderPipeline, WGPUProcDeviceCreateRenderPipeline) \
|
|
23
|
+
X(wgpuDeviceCreateSampler, WGPUProcDeviceCreateSampler) \
|
|
24
|
+
X(wgpuDeviceCreateShaderModule, WGPUProcDeviceCreateShaderModule) \
|
|
25
|
+
X(wgpuDeviceCreateTexture, WGPUProcDeviceCreateTexture) \
|
|
26
|
+
X(wgpuDeviceGetQueue, WGPUProcDeviceGetQueue) \
|
|
27
|
+
X(wgpuPipelineLayoutRelease, WGPUProcPipelineLayoutRelease) \
|
|
28
|
+
X(wgpuQueueRelease, WGPUProcQueueRelease) \
|
|
29
|
+
X(wgpuQueueWriteBuffer, WGPUProcQueueWriteBuffer) \
|
|
30
|
+
X(wgpuQueueWriteTexture, WGPUProcQueueWriteTexture) \
|
|
31
|
+
X(wgpuRenderPassEncoderDrawIndexed, WGPUProcRenderPassEncoderDrawIndexed) \
|
|
32
|
+
X(wgpuRenderPassEncoderEnd, WGPUProcRenderPassEncoderEnd) \
|
|
33
|
+
X(wgpuRenderPassEncoderRelease, WGPUProcRenderPassEncoderRelease) \
|
|
34
|
+
X(wgpuRenderPassEncoderSetBindGroup, WGPUProcRenderPassEncoderSetBindGroup) \
|
|
35
|
+
X(wgpuRenderPassEncoderSetBlendConstant, WGPUProcRenderPassEncoderSetBlendConstant) \
|
|
36
|
+
X(wgpuRenderPassEncoderSetIndexBuffer, WGPUProcRenderPassEncoderSetIndexBuffer) \
|
|
37
|
+
X(wgpuRenderPassEncoderSetPipeline, WGPUProcRenderPassEncoderSetPipeline) \
|
|
38
|
+
X(wgpuRenderPassEncoderSetScissorRect, WGPUProcRenderPassEncoderSetScissorRect) \
|
|
39
|
+
X(wgpuRenderPassEncoderSetVertexBuffer, WGPUProcRenderPassEncoderSetVertexBuffer) \
|
|
40
|
+
X(wgpuRenderPassEncoderSetViewport, WGPUProcRenderPassEncoderSetViewport) \
|
|
41
|
+
X(wgpuRenderPipelineRelease, WGPUProcRenderPipelineRelease) \
|
|
42
|
+
X(wgpuSamplerRelease, WGPUProcSamplerRelease) \
|
|
43
|
+
X(wgpuShaderModuleRelease, WGPUProcShaderModuleRelease) \
|
|
44
|
+
X(wgpuTextureCreateView, WGPUProcTextureCreateView) \
|
|
45
|
+
X(wgpuTextureRelease, WGPUProcTextureRelease) \
|
|
46
|
+
X(wgpuTextureViewRelease, WGPUProcTextureViewRelease)
|
|
47
|
+
|
|
48
|
+
namespace {
|
|
49
|
+
|
|
50
|
+
#define DECLARE_FUNCTION(name, type) type name##_function = nullptr;
|
|
51
|
+
WGPU_FUNCTIONS(DECLARE_FUNCTION)
|
|
52
|
+
#undef DECLARE_FUNCTION
|
|
53
|
+
|
|
54
|
+
std::string bridge_error;
|
|
55
|
+
|
|
56
|
+
const char* const required_function_names[] = {
|
|
57
|
+
#define FUNCTION_NAME(name, type) #name,
|
|
58
|
+
WGPU_FUNCTIONS(FUNCTION_NAME)
|
|
59
|
+
#undef FUNCTION_NAME
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
} // namespace
|
|
63
|
+
|
|
64
|
+
extern "C" {
|
|
65
|
+
|
|
66
|
+
IMGUI_RUBY_EXPORT size_t imgui_ruby_wgpu_required_function_count() {
|
|
67
|
+
return sizeof(required_function_names) / sizeof(required_function_names[0]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
IMGUI_RUBY_EXPORT const char* imgui_ruby_wgpu_required_function_name(size_t index) {
|
|
71
|
+
if (index >= imgui_ruby_wgpu_required_function_count()) {
|
|
72
|
+
return nullptr;
|
|
73
|
+
}
|
|
74
|
+
return required_function_names[index];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
IMGUI_RUBY_EXPORT bool imgui_ruby_wgpu_set_function(const char* name, void* function) {
|
|
78
|
+
if (!name || !function) {
|
|
79
|
+
bridge_error = "WebGPU function name and address must be non-null";
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#define ASSIGN_FUNCTION(function_name, type) \
|
|
84
|
+
if (std::strcmp(name, #function_name) == 0) { \
|
|
85
|
+
function_name##_function = reinterpret_cast<type>(function); \
|
|
86
|
+
return true; \
|
|
87
|
+
}
|
|
88
|
+
WGPU_FUNCTIONS(ASSIGN_FUNCTION)
|
|
89
|
+
#undef ASSIGN_FUNCTION
|
|
90
|
+
|
|
91
|
+
bridge_error = std::string("unexpected WebGPU function: ") + name;
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
IMGUI_RUBY_EXPORT bool imgui_ruby_wgpu_bridge_ready() {
|
|
96
|
+
#define CHECK_FUNCTION(name, type) \
|
|
97
|
+
if (!name##_function) { \
|
|
98
|
+
bridge_error = std::string("WebGPU function is unavailable: ") + #name; \
|
|
99
|
+
return false; \
|
|
100
|
+
}
|
|
101
|
+
WGPU_FUNCTIONS(CHECK_FUNCTION)
|
|
102
|
+
#undef CHECK_FUNCTION
|
|
103
|
+
|
|
104
|
+
bridge_error.clear();
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
IMGUI_RUBY_EXPORT const char* imgui_ruby_wgpu_bridge_error() {
|
|
109
|
+
return bridge_error.c_str();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
WGPU_EXPORT void wgpuBindGroupLayoutRelease(WGPUBindGroupLayout value) {
|
|
113
|
+
wgpuBindGroupLayoutRelease_function(value);
|
|
114
|
+
}
|
|
115
|
+
WGPU_EXPORT void wgpuBindGroupRelease(WGPUBindGroup value) {
|
|
116
|
+
wgpuBindGroupRelease_function(value);
|
|
117
|
+
}
|
|
118
|
+
WGPU_EXPORT void wgpuBufferDestroy(WGPUBuffer value) {
|
|
119
|
+
wgpuBufferDestroy_function(value);
|
|
120
|
+
}
|
|
121
|
+
WGPU_EXPORT void wgpuBufferRelease(WGPUBuffer value) {
|
|
122
|
+
wgpuBufferRelease_function(value);
|
|
123
|
+
}
|
|
124
|
+
WGPU_EXPORT WGPURenderPassEncoder wgpuCommandEncoderBeginRenderPass(
|
|
125
|
+
WGPUCommandEncoder encoder, const WGPURenderPassDescriptor* descriptor) {
|
|
126
|
+
return wgpuCommandEncoderBeginRenderPass_function(encoder, descriptor);
|
|
127
|
+
}
|
|
128
|
+
WGPU_EXPORT WGPUBindGroup wgpuDeviceCreateBindGroup(
|
|
129
|
+
WGPUDevice device, const WGPUBindGroupDescriptor* descriptor) {
|
|
130
|
+
return wgpuDeviceCreateBindGroup_function(device, descriptor);
|
|
131
|
+
}
|
|
132
|
+
WGPU_EXPORT WGPUBindGroupLayout wgpuDeviceCreateBindGroupLayout(
|
|
133
|
+
WGPUDevice device, const WGPUBindGroupLayoutDescriptor* descriptor) {
|
|
134
|
+
return wgpuDeviceCreateBindGroupLayout_function(device, descriptor);
|
|
135
|
+
}
|
|
136
|
+
WGPU_EXPORT WGPUBuffer wgpuDeviceCreateBuffer(
|
|
137
|
+
WGPUDevice device, const WGPUBufferDescriptor* descriptor) {
|
|
138
|
+
return wgpuDeviceCreateBuffer_function(device, descriptor);
|
|
139
|
+
}
|
|
140
|
+
WGPU_EXPORT WGPUPipelineLayout wgpuDeviceCreatePipelineLayout(
|
|
141
|
+
WGPUDevice device, const WGPUPipelineLayoutDescriptor* descriptor) {
|
|
142
|
+
return wgpuDeviceCreatePipelineLayout_function(device, descriptor);
|
|
143
|
+
}
|
|
144
|
+
WGPU_EXPORT WGPURenderPipeline wgpuDeviceCreateRenderPipeline(
|
|
145
|
+
WGPUDevice device, const WGPURenderPipelineDescriptor* descriptor) {
|
|
146
|
+
return wgpuDeviceCreateRenderPipeline_function(device, descriptor);
|
|
147
|
+
}
|
|
148
|
+
WGPU_EXPORT WGPUSampler wgpuDeviceCreateSampler(
|
|
149
|
+
WGPUDevice device, const WGPUSamplerDescriptor* descriptor) {
|
|
150
|
+
return wgpuDeviceCreateSampler_function(device, descriptor);
|
|
151
|
+
}
|
|
152
|
+
WGPU_EXPORT WGPUShaderModule wgpuDeviceCreateShaderModule(
|
|
153
|
+
WGPUDevice device, const WGPUShaderModuleDescriptor* descriptor) {
|
|
154
|
+
return wgpuDeviceCreateShaderModule_function(device, descriptor);
|
|
155
|
+
}
|
|
156
|
+
WGPU_EXPORT WGPUTexture wgpuDeviceCreateTexture(
|
|
157
|
+
WGPUDevice device, const WGPUTextureDescriptor* descriptor) {
|
|
158
|
+
return wgpuDeviceCreateTexture_function(device, descriptor);
|
|
159
|
+
}
|
|
160
|
+
WGPU_EXPORT WGPUQueue wgpuDeviceGetQueue(WGPUDevice device) {
|
|
161
|
+
return wgpuDeviceGetQueue_function(device);
|
|
162
|
+
}
|
|
163
|
+
WGPU_EXPORT void wgpuPipelineLayoutRelease(WGPUPipelineLayout value) {
|
|
164
|
+
wgpuPipelineLayoutRelease_function(value);
|
|
165
|
+
}
|
|
166
|
+
WGPU_EXPORT void wgpuQueueRelease(WGPUQueue value) {
|
|
167
|
+
wgpuQueueRelease_function(value);
|
|
168
|
+
}
|
|
169
|
+
WGPU_EXPORT void wgpuQueueWriteBuffer(
|
|
170
|
+
WGPUQueue queue, WGPUBuffer buffer, uint64_t offset, const void* data, size_t size) {
|
|
171
|
+
wgpuQueueWriteBuffer_function(queue, buffer, offset, data, size);
|
|
172
|
+
}
|
|
173
|
+
WGPU_EXPORT void wgpuQueueWriteTexture(
|
|
174
|
+
WGPUQueue queue, const WGPUTexelCopyTextureInfo* destination, const void* data,
|
|
175
|
+
size_t data_size, const WGPUTexelCopyBufferLayout* layout, const WGPUExtent3D* size) {
|
|
176
|
+
wgpuQueueWriteTexture_function(queue, destination, data, data_size, layout, size);
|
|
177
|
+
}
|
|
178
|
+
WGPU_EXPORT void wgpuRenderPassEncoderDrawIndexed(
|
|
179
|
+
WGPURenderPassEncoder pass, uint32_t index_count, uint32_t instance_count,
|
|
180
|
+
uint32_t first_index, int32_t base_vertex, uint32_t first_instance) {
|
|
181
|
+
wgpuRenderPassEncoderDrawIndexed_function(
|
|
182
|
+
pass, index_count, instance_count, first_index, base_vertex, first_instance);
|
|
183
|
+
}
|
|
184
|
+
WGPU_EXPORT void wgpuRenderPassEncoderEnd(WGPURenderPassEncoder pass) {
|
|
185
|
+
wgpuRenderPassEncoderEnd_function(pass);
|
|
186
|
+
}
|
|
187
|
+
WGPU_EXPORT void wgpuRenderPassEncoderRelease(WGPURenderPassEncoder pass) {
|
|
188
|
+
wgpuRenderPassEncoderRelease_function(pass);
|
|
189
|
+
}
|
|
190
|
+
WGPU_EXPORT void wgpuRenderPassEncoderSetBindGroup(
|
|
191
|
+
WGPURenderPassEncoder pass, uint32_t index, WGPUBindGroup group,
|
|
192
|
+
size_t offset_count, const uint32_t* offsets) {
|
|
193
|
+
wgpuRenderPassEncoderSetBindGroup_function(pass, index, group, offset_count, offsets);
|
|
194
|
+
}
|
|
195
|
+
WGPU_EXPORT void wgpuRenderPassEncoderSetBlendConstant(
|
|
196
|
+
WGPURenderPassEncoder pass, const WGPUColor* color) {
|
|
197
|
+
wgpuRenderPassEncoderSetBlendConstant_function(pass, color);
|
|
198
|
+
}
|
|
199
|
+
WGPU_EXPORT void wgpuRenderPassEncoderSetIndexBuffer(
|
|
200
|
+
WGPURenderPassEncoder pass, WGPUBuffer buffer, WGPUIndexFormat format,
|
|
201
|
+
uint64_t offset, uint64_t size) {
|
|
202
|
+
wgpuRenderPassEncoderSetIndexBuffer_function(pass, buffer, format, offset, size);
|
|
203
|
+
}
|
|
204
|
+
WGPU_EXPORT void wgpuRenderPassEncoderSetPipeline(
|
|
205
|
+
WGPURenderPassEncoder pass, WGPURenderPipeline pipeline) {
|
|
206
|
+
wgpuRenderPassEncoderSetPipeline_function(pass, pipeline);
|
|
207
|
+
}
|
|
208
|
+
WGPU_EXPORT void wgpuRenderPassEncoderSetScissorRect(
|
|
209
|
+
WGPURenderPassEncoder pass, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
|
|
210
|
+
wgpuRenderPassEncoderSetScissorRect_function(pass, x, y, width, height);
|
|
211
|
+
}
|
|
212
|
+
WGPU_EXPORT void wgpuRenderPassEncoderSetVertexBuffer(
|
|
213
|
+
WGPURenderPassEncoder pass, uint32_t slot, WGPUBuffer buffer,
|
|
214
|
+
uint64_t offset, uint64_t size) {
|
|
215
|
+
wgpuRenderPassEncoderSetVertexBuffer_function(pass, slot, buffer, offset, size);
|
|
216
|
+
}
|
|
217
|
+
WGPU_EXPORT void wgpuRenderPassEncoderSetViewport(
|
|
218
|
+
WGPURenderPassEncoder pass, float x, float y, float width, float height,
|
|
219
|
+
float minimum_depth, float maximum_depth) {
|
|
220
|
+
wgpuRenderPassEncoderSetViewport_function(
|
|
221
|
+
pass, x, y, width, height, minimum_depth, maximum_depth);
|
|
222
|
+
}
|
|
223
|
+
WGPU_EXPORT void wgpuRenderPipelineRelease(WGPURenderPipeline value) {
|
|
224
|
+
wgpuRenderPipelineRelease_function(value);
|
|
225
|
+
}
|
|
226
|
+
WGPU_EXPORT void wgpuSamplerRelease(WGPUSampler value) {
|
|
227
|
+
wgpuSamplerRelease_function(value);
|
|
228
|
+
}
|
|
229
|
+
WGPU_EXPORT void wgpuShaderModuleRelease(WGPUShaderModule value) {
|
|
230
|
+
wgpuShaderModuleRelease_function(value);
|
|
231
|
+
}
|
|
232
|
+
WGPU_EXPORT WGPUTextureView wgpuTextureCreateView(
|
|
233
|
+
WGPUTexture texture, const WGPUTextureViewDescriptor* descriptor) {
|
|
234
|
+
return wgpuTextureCreateView_function(texture, descriptor);
|
|
235
|
+
}
|
|
236
|
+
WGPU_EXPORT void wgpuTextureRelease(WGPUTexture value) {
|
|
237
|
+
wgpuTextureRelease_function(value);
|
|
238
|
+
}
|
|
239
|
+
WGPU_EXPORT void wgpuTextureViewRelease(WGPUTextureView value) {
|
|
240
|
+
wgpuTextureViewRelease_function(value);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
#undef WGPU_FUNCTIONS
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "yaml"
|
|
5
|
+
|
|
6
|
+
module ImGuiRuby
|
|
7
|
+
module Generator
|
|
8
|
+
class ApiEmitter
|
|
9
|
+
UNPARSED = Object.new.freeze
|
|
10
|
+
HAND_WRITTEN = %w[
|
|
11
|
+
CreateContext DestroyContext GetCurrentContext SetCurrentContext GetIO GetStyle GetDrawData
|
|
12
|
+
NewFrame EndFrame Render GetVersion Text TextColored Button SmallButton InvisibleButton
|
|
13
|
+
Checkbox RadioButton SliderFloat SliderFloat2 SliderFloat3 SliderFloat4 SliderInt
|
|
14
|
+
DragFloat DragInt InputFloat InputInt InputText ColorEdit3 ColorEdit4 Selectable MenuItem
|
|
15
|
+
ProgressBar Separator Spacing NewLine SameLine Dummy Indent Unindent SetNextWindowPos
|
|
16
|
+
SetNextWindowSize SetNextWindowCollapsed SetNextWindowFocus
|
|
17
|
+
].freeze
|
|
18
|
+
|
|
19
|
+
GENERATED_HEADER = <<~RUBY.freeze
|
|
20
|
+
# frozen_string_literal: true
|
|
21
|
+
|
|
22
|
+
# This file is generated by `rake generate`. Do not edit it manually.
|
|
23
|
+
RUBY
|
|
24
|
+
|
|
25
|
+
def initialize(metadata_dir:, output_path:, overrides_path:)
|
|
26
|
+
@definitions = JSON.parse(File.read(File.join(metadata_dir, "definitions.json")))
|
|
27
|
+
types = JSON.parse(File.read(File.join(metadata_dir, "structs_and_enums.json")))
|
|
28
|
+
@enum_values = types.fetch("enums").values.flatten.to_h do |value|
|
|
29
|
+
[value.fetch("name"), value.fetch("calc_value")]
|
|
30
|
+
end
|
|
31
|
+
@output_path = output_path
|
|
32
|
+
@overrides = YAML.safe_load_file(overrides_path, aliases: false) || {}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def generate!
|
|
36
|
+
methods = selected_definitions.map do |definition|
|
|
37
|
+
emit_method(definition)
|
|
38
|
+
end
|
|
39
|
+
File.write(@output_path, <<~RUBY)
|
|
40
|
+
#{GENERATED_HEADER}
|
|
41
|
+
|
|
42
|
+
module ImGui
|
|
43
|
+
#{methods.join("\n")}
|
|
44
|
+
end
|
|
45
|
+
RUBY
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def selected_definitions
|
|
51
|
+
candidates = @definitions.values.flatten.select do |definition|
|
|
52
|
+
public_definition?(definition)
|
|
53
|
+
end
|
|
54
|
+
candidates.group_by { |definition| snake_case(definition.fetch("funcname")) }
|
|
55
|
+
.values
|
|
56
|
+
.map { |overloads| overloads.min_by { |definition| overload_score(definition) } }
|
|
57
|
+
.sort_by { |definition| snake_case(definition.fetch("funcname")) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def public_definition?(definition)
|
|
61
|
+
return false unless definition.fetch("location", "").start_with?("imgui:")
|
|
62
|
+
return false unless definition.fetch("stname", "").empty?
|
|
63
|
+
return false if definition["isvararg"] || definition["skipped"]
|
|
64
|
+
return false if Array(definition["argsT"]).any? { |argument| argument.fetch("type") == "va_list" }
|
|
65
|
+
return false if HAND_WRITTEN.include?(definition["funcname"])
|
|
66
|
+
return false if definition.fetch("funcname").start_with?("Begin", "End")
|
|
67
|
+
|
|
68
|
+
!Array(@overrides["skip"]).include?(native_name(definition))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def overload_score(definition)
|
|
72
|
+
name = native_name(definition)
|
|
73
|
+
base = definition.fetch("cimguiname")
|
|
74
|
+
preferred_suffix = name.end_with?("_Nil", "_Str", "_Bool") ? 0 : 1
|
|
75
|
+
[name == base ? 0 : 1, preferred_suffix, Array(definition["argsT"]).length]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def emit_method(definition)
|
|
79
|
+
ruby_name = snake_case(definition.fetch("funcname"))
|
|
80
|
+
arguments = Array(definition["argsT"]).map do |argument|
|
|
81
|
+
[argument.fetch("name"), argument.fetch("type")]
|
|
82
|
+
end
|
|
83
|
+
defaults = definition.fetch("defaults", {}).filter_map do |name, value|
|
|
84
|
+
parsed = ruby_default(value)
|
|
85
|
+
[name, parsed] unless parsed.equal?(UNPARSED)
|
|
86
|
+
end.to_h
|
|
87
|
+
|
|
88
|
+
<<~RUBY.chomp
|
|
89
|
+
__send__(:define_generated_method,
|
|
90
|
+
:#{ruby_name},
|
|
91
|
+
:#{renamed_native_name(definition)},
|
|
92
|
+
#{ruby_literal(arguments)},
|
|
93
|
+
#{ruby_literal(defaults)}
|
|
94
|
+
)
|
|
95
|
+
RUBY
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def ruby_literal(value)
|
|
99
|
+
case value
|
|
100
|
+
when Array
|
|
101
|
+
"[#{value.map { |item| ruby_literal(item) }.join(", ")}]"
|
|
102
|
+
when Hash
|
|
103
|
+
entries = value.map do |key, item|
|
|
104
|
+
"#{ruby_literal(key)} => #{ruby_literal(item)}"
|
|
105
|
+
end
|
|
106
|
+
"{#{entries.join(", ")}}"
|
|
107
|
+
when String, Integer, Float, TrueClass, FalseClass, NilClass
|
|
108
|
+
value.inspect
|
|
109
|
+
else
|
|
110
|
+
raise ArgumentError, "unsupported generated literal: #{value.class}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def renamed_native_name(definition)
|
|
115
|
+
name = native_name(definition)
|
|
116
|
+
@overrides.fetch("rename", {}).fetch(name, name)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def native_name(definition)
|
|
120
|
+
definition["ov_cimguiname"] || definition.fetch("cimguiname")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def ruby_default(value)
|
|
124
|
+
source = value.to_s.strip
|
|
125
|
+
return nil if source.match?(/\A(?:NULL|nullptr|\(\(void\*\)0\))\z/)
|
|
126
|
+
return true if source == "true"
|
|
127
|
+
return false if source == "false"
|
|
128
|
+
return source[1...-1] if source.match?(/\A".*"\z/)
|
|
129
|
+
|
|
130
|
+
vector = source.match(/\AImVec([24])\((.*)\)\z/)
|
|
131
|
+
if vector
|
|
132
|
+
values = vector[2].split(",").map { |item| numeric_default(item.strip) }
|
|
133
|
+
return UNPARSED if values.any? { |item| item.equal?(UNPARSED) }
|
|
134
|
+
|
|
135
|
+
return values
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
numeric_default(source)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def numeric_default(source)
|
|
142
|
+
normalized = source.delete_suffix("f")
|
|
143
|
+
return Integer(normalized, 0) if normalized.match?(/\A-?(?:0x[\da-f]+|\d+)\z/i)
|
|
144
|
+
return Float(normalized) if normalized.match?(/\A-?(?:\d+\.\d*|\.\d+)(?:e[+-]?\d+)?\z/i)
|
|
145
|
+
return Float::MAX if source == "FLT_MAX"
|
|
146
|
+
return -Float::MIN if source == "-FLT_MIN"
|
|
147
|
+
return @enum_values.fetch(source) if @enum_values.key?(source)
|
|
148
|
+
|
|
149
|
+
enum_parts = source.split("|").map(&:strip)
|
|
150
|
+
if enum_parts.length > 1 && enum_parts.all? { |part| @enum_values.key?(part) }
|
|
151
|
+
return enum_parts.reduce(0) { |value, part| value | @enum_values.fetch(part) }
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
UNPARSED
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def snake_case(name)
|
|
158
|
+
name.gsub(/([A-Z]+)([A-Z][a-z])/, '\\1_\\2')
|
|
159
|
+
.gsub(/([a-z\d])([A-Z])/, '\\1_\\2')
|
|
160
|
+
.downcase
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|