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,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is generated by `rake generate`. Do not edit it manually.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module ImGui
|
|
7
|
+
module Native
|
|
8
|
+
typedef :pointer, :ImBitArrayForNamedKeys
|
|
9
|
+
typedef :pointer, :ImBitArrayPtr
|
|
10
|
+
callback :ImDrawCallback, [:pointer, :pointer], :void
|
|
11
|
+
typedef :int, :ImDrawFlags
|
|
12
|
+
typedef :ushort, :ImDrawIdx
|
|
13
|
+
typedef :int, :ImDrawListFlags
|
|
14
|
+
typedef :pointer, :ImFileHandle
|
|
15
|
+
typedef :int, :ImFontAtlasFlags
|
|
16
|
+
typedef :int, :ImGuiActivateFlags
|
|
17
|
+
typedef :int, :ImGuiBackendFlags
|
|
18
|
+
typedef :int, :ImGuiButtonFlags
|
|
19
|
+
typedef :int, :ImGuiChildFlags
|
|
20
|
+
typedef :int, :ImGuiCol
|
|
21
|
+
typedef :int, :ImGuiColorEditFlags
|
|
22
|
+
typedef :int, :ImGuiComboFlags
|
|
23
|
+
typedef :int, :ImGuiCond
|
|
24
|
+
typedef :int, :ImGuiConfigFlags
|
|
25
|
+
callback :ImGuiContextHookCallback, [:pointer, :pointer], :void
|
|
26
|
+
typedef :int, :ImGuiDataAuthority
|
|
27
|
+
typedef :int, :ImGuiDataType
|
|
28
|
+
typedef :int, :ImGuiDebugLogFlags
|
|
29
|
+
typedef :int, :ImGuiDockNodeFlags
|
|
30
|
+
typedef :int, :ImGuiDragDropFlags
|
|
31
|
+
callback :ImGuiErrorCallback, [:pointer, :pointer, :string], :void
|
|
32
|
+
typedef :int, :ImGuiFocusRequestFlags
|
|
33
|
+
typedef :int, :ImGuiFocusedFlags
|
|
34
|
+
typedef :int, :ImGuiHoveredFlags
|
|
35
|
+
typedef :uint, :ImGuiID
|
|
36
|
+
typedef :int, :ImGuiInputFlags
|
|
37
|
+
callback :ImGuiInputTextCallback, [:pointer], :int
|
|
38
|
+
typedef :int, :ImGuiInputTextFlags
|
|
39
|
+
typedef :int, :ImGuiItemFlags
|
|
40
|
+
typedef :int, :ImGuiItemStatusFlags
|
|
41
|
+
typedef :int, :ImGuiKeyChord
|
|
42
|
+
typedef :pointer, :ImGuiKeyRoutingIndex
|
|
43
|
+
typedef :int, :ImGuiLayoutType
|
|
44
|
+
typedef :int, :ImGuiLogFlags
|
|
45
|
+
callback :ImGuiMemAllocFunc, [:size_t, :pointer], :pointer
|
|
46
|
+
callback :ImGuiMemFreeFunc, [:pointer, :pointer], :void
|
|
47
|
+
typedef :int, :ImGuiMouseButton
|
|
48
|
+
typedef :int, :ImGuiMouseCursor
|
|
49
|
+
typedef :int, :ImGuiMultiSelectFlags
|
|
50
|
+
typedef :int, :ImGuiNavMoveFlags
|
|
51
|
+
typedef :int, :ImGuiNavRenderCursorFlags
|
|
52
|
+
typedef :int, :ImGuiNextItemDataFlags
|
|
53
|
+
typedef :int, :ImGuiNextWindowDataFlags
|
|
54
|
+
typedef :int, :ImGuiOldColumnFlags
|
|
55
|
+
typedef :int, :ImGuiPopupFlags
|
|
56
|
+
typedef :int, :ImGuiScrollFlags
|
|
57
|
+
typedef :int, :ImGuiSelectableFlags
|
|
58
|
+
typedef :pointer, :ImGuiSelectionUserData
|
|
59
|
+
typedef :int, :ImGuiSeparatorFlags
|
|
60
|
+
callback :ImGuiSizeCallback, [:pointer], :void
|
|
61
|
+
typedef :int, :ImGuiSliderFlags
|
|
62
|
+
typedef :int, :ImGuiStyleVar
|
|
63
|
+
typedef :int, :ImGuiTabBarFlags
|
|
64
|
+
typedef :int, :ImGuiTabItemFlags
|
|
65
|
+
typedef :int, :ImGuiTableBgTarget
|
|
66
|
+
typedef :int, :ImGuiTableColumnFlags
|
|
67
|
+
typedef :pointer, :ImGuiTableColumnIdx
|
|
68
|
+
typedef :ushort, :ImGuiTableDrawChannelIdx
|
|
69
|
+
typedef :int, :ImGuiTableFlags
|
|
70
|
+
typedef :int, :ImGuiTableRowFlags
|
|
71
|
+
typedef :int, :ImGuiTextFlags
|
|
72
|
+
typedef :int, :ImGuiTooltipFlags
|
|
73
|
+
typedef :int, :ImGuiTreeNodeFlags
|
|
74
|
+
typedef :int, :ImGuiTypingSelectFlags
|
|
75
|
+
typedef :int, :ImGuiViewportFlags
|
|
76
|
+
typedef :int, :ImGuiWindowFlags
|
|
77
|
+
typedef :int, :ImGuiWindowRefreshFlags
|
|
78
|
+
typedef :int, :ImPoolIdx
|
|
79
|
+
typedef :pointer, :ImS16
|
|
80
|
+
typedef :pointer, :ImS32
|
|
81
|
+
typedef :pointer, :ImS64
|
|
82
|
+
typedef :char, :ImS8
|
|
83
|
+
typedef :pointer, :ImStbTexteditState
|
|
84
|
+
typedef :ulong_long, :ImTextureID
|
|
85
|
+
typedef :ushort, :ImU16
|
|
86
|
+
typedef :uint, :ImU32
|
|
87
|
+
typedef :ulong_long, :ImU64
|
|
88
|
+
typedef :uchar, :ImU8
|
|
89
|
+
typedef :ushort, :ImWchar
|
|
90
|
+
typedef :ushort, :ImWchar16
|
|
91
|
+
typedef :uint, :ImWchar32
|
|
92
|
+
end
|
|
93
|
+
end
|
data/lib/imgui/native.rb
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ffi"
|
|
4
|
+
|
|
5
|
+
module ImGui
|
|
6
|
+
module Native
|
|
7
|
+
extend FFI::Library
|
|
8
|
+
|
|
9
|
+
LIBRARY_BASENAME = "cimgui_ruby"
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
alias ffi_attach_function attach_function
|
|
13
|
+
|
|
14
|
+
attr_reader :loaded_path
|
|
15
|
+
|
|
16
|
+
def attach_function(*signature)
|
|
17
|
+
ruby_name = signature.fetch(0)
|
|
18
|
+
function_signatures[ruby_name] = signature
|
|
19
|
+
registered_function_names << ruby_name unless registered_function_names.include?(ruby_name)
|
|
20
|
+
define_lazy_function(ruby_name)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def load!(path: nil)
|
|
24
|
+
return loaded_path if loaded?
|
|
25
|
+
|
|
26
|
+
failures = []
|
|
27
|
+
library_candidates(path).each do |candidate|
|
|
28
|
+
begin
|
|
29
|
+
ffi_lib candidate
|
|
30
|
+
@loaded_path = candidate
|
|
31
|
+
return loaded_path
|
|
32
|
+
rescue LoadError, FFI::NotFoundError => error
|
|
33
|
+
failures << "#{candidate}: #{error.message.lines.first&.strip}"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
message = <<~MESSAGE
|
|
38
|
+
Unable to load #{library_filename}.
|
|
39
|
+
Set IMGUI_RUBY_LIB to the compiled library, install the platform-specific
|
|
40
|
+
imgui-ruby gem, or build the source gem with CMake and a C++17 compiler.
|
|
41
|
+
Tried:
|
|
42
|
+
#{failures.map { |failure| " - #{failure}" }.join("\n")}
|
|
43
|
+
MESSAGE
|
|
44
|
+
raise LibraryLoadError, message
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def loaded?
|
|
48
|
+
!@loaded_path.nil?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def registered_functions
|
|
52
|
+
registered_function_names.dup.freeze
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def bind_all!
|
|
56
|
+
load!
|
|
57
|
+
function_signatures.keys.each { |name| bind_function!(name) }
|
|
58
|
+
true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def library_candidates(explicit_path = nil)
|
|
62
|
+
requested = explicit_path || ENV["IMGUI_RUBY_LIB"]
|
|
63
|
+
candidates = []
|
|
64
|
+
candidates << File.expand_path(requested) if requested && !requested.empty?
|
|
65
|
+
|
|
66
|
+
candidates.concat(vendored_library_candidates)
|
|
67
|
+
candidates.concat([LIBRARY_BASENAME, "lib#{LIBRARY_BASENAME}"])
|
|
68
|
+
candidates.uniq
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def library_filename
|
|
72
|
+
"lib#{LIBRARY_BASENAME}.#{FFI::Platform::LIBSUFFIX}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def function_signatures
|
|
78
|
+
@function_signatures ||= {}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def registered_function_names
|
|
82
|
+
@registered_function_names ||= []
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def define_lazy_function(ruby_name)
|
|
86
|
+
define_singleton_method(ruby_name) do |*arguments|
|
|
87
|
+
load!
|
|
88
|
+
bind_function!(ruby_name)
|
|
89
|
+
public_send(ruby_name, *arguments)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def bind_function!(ruby_name)
|
|
94
|
+
signature = function_signatures.fetch(ruby_name)
|
|
95
|
+
singleton_class.send(:remove_method, ruby_name)
|
|
96
|
+
ffi_attach_function(*signature)
|
|
97
|
+
function_signatures.delete(ruby_name)
|
|
98
|
+
rescue FFI::NotFoundError => error
|
|
99
|
+
define_lazy_function(ruby_name)
|
|
100
|
+
raise MissingSymbolError, "#{ruby_name} is not exported by #{loaded_path}: #{error.message}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def vendored_library_candidates
|
|
104
|
+
vendor_root = File.expand_path("../../vendor", __dir__)
|
|
105
|
+
platforms = ["#{FFI::Platform::ARCH}-#{FFI::Platform::OS}"]
|
|
106
|
+
if FFI::Platform::ARCH == "aarch64"
|
|
107
|
+
platforms << "arm64-#{FFI::Platform::OS}"
|
|
108
|
+
end
|
|
109
|
+
filenames = [library_filename]
|
|
110
|
+
filenames << "#{LIBRARY_BASENAME}.dll" if FFI::Platform.windows?
|
|
111
|
+
|
|
112
|
+
vendor_roots = [vendor_root]
|
|
113
|
+
$LOAD_PATH.each do |load_path|
|
|
114
|
+
vendor_roots << File.join(load_path, "imgui", "vendor")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
vendor_roots.uniq.flat_map do |root|
|
|
118
|
+
filenames.flat_map do |filename|
|
|
119
|
+
platforms.map { |platform| File.join(root, platform, filename) } + [File.join(root, filename)]
|
|
120
|
+
end
|
|
121
|
+
end.select { |candidate| File.file?(candidate) }
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
require_relative "native/typedefs"
|
|
128
|
+
require_relative "native/enums"
|
|
129
|
+
require_relative "native/structs"
|
|
130
|
+
require_relative "native/functions"
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ImPlot
|
|
4
|
+
class Error < ImGui::Error; end
|
|
5
|
+
class NoContextError < Error; end
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def create_context
|
|
9
|
+
ImGui.__send__(:guard_context!)
|
|
10
|
+
context = ImGui::Native.ImPlot_CreateContext
|
|
11
|
+
raise Error, "cimplot returned a null context" if null_pointer?(context)
|
|
12
|
+
|
|
13
|
+
context
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def destroy_context(context = nil)
|
|
17
|
+
context ||= current_context
|
|
18
|
+
return if context.nil?
|
|
19
|
+
|
|
20
|
+
ImGui.__send__(:guard_context!)
|
|
21
|
+
ImGui::Native.ImPlot_DestroyContext(context)
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def current_context
|
|
26
|
+
context = ImGui::Native.ImPlot_GetCurrentContext
|
|
27
|
+
null_pointer?(context) ? nil : context
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def current_context=(context)
|
|
31
|
+
ImGui.__send__(:guard_context!)
|
|
32
|
+
ImGui::Native.ImPlot_SetCurrentContext(context)
|
|
33
|
+
context
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def plot(title, size: [-1, 0], flags: 0, &block)
|
|
37
|
+
plot_guard!
|
|
38
|
+
opened = ImGui::Native.ImPlot_BeginPlot(title.to_s, ImGui::StructValue.vec2(size), Integer(flags))
|
|
39
|
+
plot_scope(:plot, :ImPlot_EndPlot, opened, &block)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def subplots(title, rows:, columns:, size: [-1, 0], flags: 0, row_ratios: nil, column_ratios: nil, &block)
|
|
43
|
+
plot_guard!
|
|
44
|
+
row_pointer = optional_float_array(row_ratios, rows)
|
|
45
|
+
column_pointer = optional_float_array(column_ratios, columns)
|
|
46
|
+
opened = ImGui::Native.ImPlot_BeginSubplots(
|
|
47
|
+
title.to_s,
|
|
48
|
+
Integer(rows),
|
|
49
|
+
Integer(columns),
|
|
50
|
+
ImGui::StructValue.vec2(size),
|
|
51
|
+
Integer(flags),
|
|
52
|
+
row_pointer,
|
|
53
|
+
column_pointer
|
|
54
|
+
)
|
|
55
|
+
plot_scope(:subplots, :ImPlot_EndSubplots, opened, &block)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def setup_axes(x_label = nil, y_label = nil, x_flags: 0, y_flags: 0)
|
|
59
|
+
plot_guard!
|
|
60
|
+
ImGui::Native.ImPlot_SetupAxes(x_label&.to_s, y_label&.to_s, Integer(x_flags), Integer(y_flags))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def setup_axis(axis, label = nil, flags: 0)
|
|
64
|
+
plot_guard!
|
|
65
|
+
ImGui::Native.ImPlot_SetupAxis(Integer(axis), label&.to_s, Integer(flags))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def setup_axis_limits(axis, minimum, maximum, condition: 0)
|
|
69
|
+
plot_guard!
|
|
70
|
+
ImGui::Native.ImPlot_SetupAxisLimits(Integer(axis), Float(minimum), Float(maximum), Integer(condition))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def setup_axes_limits(x_minimum, x_maximum, y_minimum, y_maximum, condition: 0)
|
|
74
|
+
plot_guard!
|
|
75
|
+
ImGui::Native.ImPlot_SetupAxesLimits(
|
|
76
|
+
Float(x_minimum),
|
|
77
|
+
Float(x_maximum),
|
|
78
|
+
Float(y_minimum),
|
|
79
|
+
Float(y_maximum),
|
|
80
|
+
Integer(condition)
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def plot_line(label, values, xs: nil, x_scale: 1.0, x_start: 0.0, flags: 0, offset: 0)
|
|
85
|
+
plot_series(:ImPlot_PlotLine, label, values, xs, x_scale, x_start, flags, offset)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def plot_scatter(label, values, xs: nil, x_scale: 1.0, x_start: 0.0, flags: 0, offset: 0)
|
|
89
|
+
plot_series(:ImPlot_PlotScatter, label, values, xs, x_scale, x_start, flags, offset)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def plot_stairs(label, values, xs: nil, x_scale: 1.0, x_start: 0.0, flags: 0, offset: 0)
|
|
93
|
+
plot_series(:ImPlot_PlotStairs, label, values, xs, x_scale, x_start, flags, offset)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def plot_bars(label, values, xs: nil, bar_size: 0.67, shift: 0.0, flags: 0, offset: 0)
|
|
97
|
+
plot_guard!
|
|
98
|
+
ys = double_array(values)
|
|
99
|
+
stride = FFI.type_size(:double)
|
|
100
|
+
if xs
|
|
101
|
+
x_values = double_array(xs, expected: values.length)
|
|
102
|
+
return ImGui::Native.ImPlot_PlotBars_doublePtrdoublePtr(
|
|
103
|
+
label.to_s, x_values, ys, values.length, Float(bar_size), Integer(flags), Integer(offset), stride
|
|
104
|
+
)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
ImGui::Native.ImPlot_PlotBars_doublePtrInt(
|
|
108
|
+
label.to_s, ys, values.length, Float(bar_size), Float(shift), Integer(flags), Integer(offset), stride
|
|
109
|
+
)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def plot_histogram(label, values, bins: Bin::Sturges, bar_scale: 1.0, range: nil, flags: 0)
|
|
113
|
+
plot_guard!
|
|
114
|
+
data = double_array(values)
|
|
115
|
+
native_range = plot_range(range)
|
|
116
|
+
ImGui::Native.ImPlot_PlotHistogram_doublePtr(
|
|
117
|
+
label.to_s,
|
|
118
|
+
data,
|
|
119
|
+
values.length,
|
|
120
|
+
Integer(bins),
|
|
121
|
+
Float(bar_scale),
|
|
122
|
+
native_range,
|
|
123
|
+
Integer(flags)
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def style_color(index, color)
|
|
128
|
+
plot_guard!
|
|
129
|
+
ImGui::Native.ImPlot_PushStyleColor_Vec4(Integer(index), ImGui::StructValue.vec4(color))
|
|
130
|
+
pushed = true
|
|
131
|
+
return manual_plot_push(:style_color, :ImPlot_PopStyleColor, [1]) unless block_given?
|
|
132
|
+
|
|
133
|
+
yield
|
|
134
|
+
ensure
|
|
135
|
+
ImGui::Native.ImPlot_PopStyleColor(1) if pushed && block_given?
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def style_var(index, value)
|
|
139
|
+
plot_guard!
|
|
140
|
+
if value.is_a?(Array)
|
|
141
|
+
ImGui::Native.ImPlot_PushStyleVar_Vec2(Integer(index), ImGui::StructValue.vec2(value))
|
|
142
|
+
else
|
|
143
|
+
ImGui::Native.ImPlot_PushStyleVar_Float(Integer(index), Float(value))
|
|
144
|
+
end
|
|
145
|
+
pushed = true
|
|
146
|
+
return manual_plot_push(:style_var, :ImPlot_PopStyleVar, [1]) unless block_given?
|
|
147
|
+
|
|
148
|
+
yield
|
|
149
|
+
ensure
|
|
150
|
+
ImGui::Native.ImPlot_PopStyleVar(1) if pushed && block_given?
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def end_plot
|
|
154
|
+
close_plot_scope(:plot)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def end_subplots
|
|
158
|
+
close_plot_scope(:subplots)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def pop_style_color
|
|
162
|
+
close_plot_scope(:style_color)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def pop_style_var
|
|
166
|
+
close_plot_scope(:style_var)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
private
|
|
170
|
+
|
|
171
|
+
def plot_series(prefix, label, values, xs, x_scale, x_start, flags, offset)
|
|
172
|
+
plot_guard!
|
|
173
|
+
ys = double_array(values)
|
|
174
|
+
stride = FFI.type_size(:double)
|
|
175
|
+
if xs
|
|
176
|
+
x_values = double_array(xs, expected: values.length)
|
|
177
|
+
function = "#{prefix}_doublePtrdoublePtr".to_sym
|
|
178
|
+
return ImGui::Native.public_send(
|
|
179
|
+
function, label.to_s, x_values, ys, values.length, Integer(flags), Integer(offset), stride
|
|
180
|
+
)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
function = "#{prefix}_doublePtrInt".to_sym
|
|
184
|
+
ImGui::Native.public_send(
|
|
185
|
+
function,
|
|
186
|
+
label.to_s,
|
|
187
|
+
ys,
|
|
188
|
+
values.length,
|
|
189
|
+
Float(x_scale),
|
|
190
|
+
Float(x_start),
|
|
191
|
+
Integer(flags),
|
|
192
|
+
Integer(offset),
|
|
193
|
+
stride
|
|
194
|
+
)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def plot_scope(kind, end_function, opened)
|
|
198
|
+
unless block_given?
|
|
199
|
+
plot_scope_stack << [kind, end_function, []] if opened
|
|
200
|
+
return opened
|
|
201
|
+
end
|
|
202
|
+
return false unless opened
|
|
203
|
+
|
|
204
|
+
begin
|
|
205
|
+
yield
|
|
206
|
+
ensure
|
|
207
|
+
ImGui::Native.public_send(end_function)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def manual_plot_push(kind, pop_function, arguments)
|
|
212
|
+
plot_scope_stack << [kind, pop_function, arguments]
|
|
213
|
+
true
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def close_plot_scope(expected)
|
|
217
|
+
plot_guard!
|
|
218
|
+
scope = plot_scope_stack.pop
|
|
219
|
+
unless scope&.first == expected
|
|
220
|
+
plot_scope_stack << scope if scope
|
|
221
|
+
raise ImGui::StackError, "expected #{expected} scope, found #{scope&.first || "none"}"
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
ImGui::Native.public_send(scope.fetch(1), *scope.fetch(2))
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def plot_scope_stack
|
|
228
|
+
Thread.current.thread_variable_get(:imgui_ruby_plot_scope_stack) || begin
|
|
229
|
+
stack = []
|
|
230
|
+
Thread.current.thread_variable_set(:imgui_ruby_plot_scope_stack, stack)
|
|
231
|
+
stack
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def plot_guard!
|
|
236
|
+
ImGui.__send__(:guard_context!)
|
|
237
|
+
raise NoContextError, "create an ImPlot context before plotting" unless current_context
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def double_array(values, expected: nil)
|
|
241
|
+
array = Array(values)
|
|
242
|
+
raise ArgumentError, "expected #{expected} values" if expected && array.length != expected
|
|
243
|
+
raise ArgumentError, "plot data cannot be empty" if array.empty?
|
|
244
|
+
|
|
245
|
+
pointer = FFI::MemoryPointer.new(:double, array.length)
|
|
246
|
+
pointer.write_array_of_double(array.map { |value| Float(value) })
|
|
247
|
+
pointer
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def optional_float_array(values, expected)
|
|
251
|
+
return nil if values.nil?
|
|
252
|
+
|
|
253
|
+
array = Array(values)
|
|
254
|
+
raise ArgumentError, "expected #{expected} ratios" unless array.length == expected
|
|
255
|
+
|
|
256
|
+
pointer = FFI::MemoryPointer.new(:float, array.length)
|
|
257
|
+
pointer.write_array_of_float(array.map { |value| Float(value) })
|
|
258
|
+
pointer
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def plot_range(value)
|
|
262
|
+
minimum, maximum = value ? Array(value) : [0.0, 0.0]
|
|
263
|
+
range = ImGui::Native::ImPlotRange.new
|
|
264
|
+
range[:Min] = Float(minimum)
|
|
265
|
+
range[:Max] = Float(maximum)
|
|
266
|
+
range
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def null_pointer?(pointer)
|
|
270
|
+
pointer.nil? || pointer.respond_to?(:null?) && pointer.null?
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|