Skip to content

Commit

Permalink
fixup! Implement (very) basic Makie integration
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesWrigley committed Jul 28, 2024
1 parent 4a6cf6e commit ea193ba
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 16 deletions.
17 changes: 9 additions & 8 deletions examples/makie_demo.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import GLFW
using GLMakie
import GLMakie.Makie as Makie
import CImGui as ig
import ModernGL as gl

Expand All @@ -25,17 +26,17 @@ function makie_demo(; engine=nothing)
io.ConfigFlags = unsafe_load(io.ConfigFlags) | ig.lib.ImGuiConfigFlags_ViewportsEnable

# Start the GUI
ig.render(ctx; engine, window_size=(800, 600), window_title="ImGui Window") do
if ig.Begin("Makie demo")
ig.render(ctx; engine, window_size=(1280, 760), window_title="ImGui Window") do
ig.Begin("Makie demo")

if ig.Button("Random data")
data[] = generate_data()
end
if ig.Button("Random data")
data[] = generate_data()
end

ig.MakieFigure("plot", f)
ig.MakieFigure("plot", f)
ig.Text("In scene: $(mouseposition(ax))")

ig.End()
end
ig.End()
end
end

Expand Down
56 changes: 48 additions & 8 deletions ext/MakieIntegration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ GLMakie.framebuffer_size(window::ImMakieWindow) = GLMakie.framebuffer_size(windo
GLMakie.ShaderAbstractions.native_switch_context!(x::ImMakieWindow) = GLFW.MakeContextCurrent(x.glfw_window)
GLMakie.ShaderAbstractions.native_context_alive(x::ImMakieWindow) = GLFW.is_initialized() && x.glfw_window != C_NULL

# This is called by GLMakie.display() to set up connections to GLFW, we'll need
# to implement this properly later to handle interactions.
GLMakie.Makie.connect_screen(::GLMakie.Scene, ::GLMakie.Screen{ImMakieWindow}) = nothing
# This is called by GLMakie.display() to set up connections to GLFW for
# mouse/keyboard events etc. We disable it explicitly because we deliver the
# events in an immediate-mode fashion within MakieFigure().
GLMakie.connect_screen(::GLMakie.Scene, ::GLMakie.Screen{ImMakieWindow}) = nothing

# Modified copy of apply_config!() with all GLFW/renderloop things removed
# See: https://github.com/MakieOrg/Makie.jl/blob/4c4eaa1f3a7f7b3777a4b8ab38388a48c0eee6ce/GLMakie/src/screen.jl#L343
Expand All @@ -84,7 +85,7 @@ function apply_config!(screen::GLMakie.Screen, config::GLMakie.ScreenConfig)
screen.config = config
end

function ig.MakieFigure(title_id::String, f::GLMakie.Figure)
function ig.MakieFigure(title_id::String, f::GLMakie.Figure; auto_resize_x=true, auto_resize_y=false)
id = ig.GetID(title_id)

if !haskey(makie_context, id)
Expand Down Expand Up @@ -122,21 +123,29 @@ function ig.MakieFigure(title_id::String, f::GLMakie.Figure)
apply_config!(screen, config)

makie_context[id] = ImMakieFigure(f, screen)
scene = GLMakie.Makie.get_scene(f)
scene.events.window_open[] = true
display(screen, f)
end

imfigure = makie_context[id]
scene = GLMakie.Makie.get_scene(f)

region_avail = ig.GetContentRegionAvail()
region_size = (Int(region_avail.x), Int(region_avail.y))
scene_size = size(GLMakie.Makie.get_scene(f))
if scene_size != region_size && all(region_size .> 0)
@debug "resizing $(scene_size) -> $(region_size)"
resize!(f, region_size[1], region_size[2])
scene_size = size(scene)
new_size = (auto_resize_x ? region_size[1] : scene_size[1],
auto_resize_y ? region_size[2] : scene_size[2])

if scene_size != new_size && all(new_size .> 0)
@debug "resizing $(scene_size) -> $(new_size)"
scene.events.window_area[] = GLMakie.Rect2i(0, 0, Int(new_size[1]), Int(new_size[2]))
resize!(f, new_size[1], new_size[2])
end

if GLMakie.requires_update(imfigure.screen)
@debug "rendering"
notify(imfigure.screen.render_tick)
GLMakie.render_frame(imfigure.screen)
end

Expand All @@ -146,6 +155,37 @@ function ig.MakieFigure(title_id::String, f::GLMakie.Figure)
# GLMakie seems to use flipped Y coordinates compared to ImGui,
# so we set these coordinates to flip the image.
(0, 1), (1, 0))

# ig.igSetItemKeyOwner(ig.ImGuiKey_MouseWheelY, 0)
# ig.igSetItemKeyOwner(ig.ImGuiKey_MouseWheelX, 0)

# Update the scene events
if scene.events.hasfocus[] != ig.IsItemHovered()
scene.events.hasfocus[] = ig.IsItemHovered()
end
if scene.events.entered_window[] != ig.IsItemHovered()
scene.events.entered_window[] = ig.IsItemHovered()
end

io = ig.GetIO()
if ig.IsItemHovered()
pos = ig.GetMousePos()
cursor_pos = ig.GetCursorScreenPos()
item_spacing = unsafe_load(ig.GetStyle().ItemSpacing.y)
new_pos = (pos.x - cursor_pos.x, abs(pos.y - cursor_pos.y) - item_spacing)
if new_pos != scene.events.mouseposition[]
scene.events.mouseposition[] = new_pos
end

wheel_y = unsafe_load(io.MouseWheel)
wheel_x = unsafe_load(io.MouseWheelH)
if (wheel_x, wheel_y) != scene.events.scroll[]
scene.events.scroll[] = (wheel_x, wheel_y)
end
end

ig.Text("Mouse position: $(scene.events.mouseposition[])")
ig.Text("Scene size: $(size(scene))")
end

function __init__()
Expand Down

0 comments on commit ea193ba

Please sign in to comment.