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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +273 -0
  4. data/Rakefile +97 -0
  5. data/api/v1.json +53 -0
  6. data/ext/CMakeLists.txt +128 -0
  7. data/ext/Rakefile +31 -0
  8. data/ext/backend_function_bridge.cpp +180 -0
  9. data/ext/backend_function_bridge.h +40 -0
  10. data/ext/build_cimgui.rb +59 -0
  11. data/ext/extconf.rb +25 -0
  12. data/ext/glfw_vulkan_bridge.cpp +14 -0
  13. data/ext/imgui_ruby_build_config.h +17 -0
  14. data/ext/imgui_ruby_glfw.cpp +73 -0
  15. data/ext/imgui_ruby_sdl3.cpp +70 -0
  16. data/ext/imgui_ruby_wgpu.cpp +75 -0
  17. data/ext/install_cimgui.rb +25 -0
  18. data/ext/webgpu_function_bridge.cpp +245 -0
  19. data/generator/api_emitter.rb +164 -0
  20. data/generator/emitter.rb +317 -0
  21. data/generator/generate.rb +47 -0
  22. data/generator/native-dependencies.yml +88 -0
  23. data/generator/native_dependency_lock.rb +78 -0
  24. data/generator/native_dependency_snapshot.rb +159 -0
  25. data/generator/overrides.yml +11 -0
  26. data/generator/type_mapper.rb +112 -0
  27. data/generator/update_vendor.rb +30 -0
  28. data/lib/imgui/api.rb +88 -0
  29. data/lib/imgui/api_generated.rb +1633 -0
  30. data/lib/imgui/api_support.rb +144 -0
  31. data/lib/imgui/backends/glfw.rb +75 -0
  32. data/lib/imgui/backends/opengl3.rb +44 -0
  33. data/lib/imgui/backends/sdl3.rb +133 -0
  34. data/lib/imgui/backends/wgpu.rb +176 -0
  35. data/lib/imgui/backends.rb +60 -0
  36. data/lib/imgui/draw_data.rb +43 -0
  37. data/lib/imgui/dsl.rb +311 -0
  38. data/lib/imgui/dsl_support.rb +107 -0
  39. data/lib/imgui/easy_loop.rb +25 -0
  40. data/lib/imgui/errors.rb +11 -0
  41. data/lib/imgui/fonts.rb +46 -0
  42. data/lib/imgui/io.rb +91 -0
  43. data/lib/imgui/layout.rb +138 -0
  44. data/lib/imgui/memory_pool.rb +18 -0
  45. data/lib/imgui/native/enums.rb +2251 -0
  46. data/lib/imgui/native/functions.rb +1470 -0
  47. data/lib/imgui/native/structs.rb +1926 -0
  48. data/lib/imgui/native/typedefs.rb +93 -0
  49. data/lib/imgui/native.rb +130 -0
  50. data/lib/imgui/plot/api.rb +273 -0
  51. data/lib/imgui/plot/native/enums.rb +593 -0
  52. data/lib/imgui/plot/native/functions.rb +749 -0
  53. data/lib/imgui/plot/native/structs.rb +363 -0
  54. data/lib/imgui/plot/native/typedefs.rb +79 -0
  55. data/lib/imgui/plot.rb +13 -0
  56. data/lib/imgui/struct_value.rb +33 -0
  57. data/lib/imgui/style.rb +44 -0
  58. data/lib/imgui/value.rb +104 -0
  59. data/lib/imgui/version.rb +5 -0
  60. data/lib/imgui/widgets.rb +187 -0
  61. data/lib/imgui.rb +30 -0
  62. data/rakelib/platform_gem.rake +54 -0
  63. data/rakelib/source_gem.rake +75 -0
  64. 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