Skip to content

Commit

Permalink
DataInspector fixes (#3454)
Browse files Browse the repository at this point in the history
* don't apply transform to displayed positions

* fix depth order in DataInspector

* cleanup bookkeeping

* switch to full transformation in tooltip

* update NEWS [skip ci]

* call inspector_clear when invalidating last selection

* update NEWS

---------

Co-authored-by: Simon <sdanisch@protonmail.com>
  • Loading branch information
ffreyer and SimonDanisch authored Dec 18, 2023
1 parent b6fea6d commit d11b786
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 32 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## master

- DataInspector Fixes: Fixed depth order, positional labels being in transformed space and `:inspector_clear` not getting called when moving from one plot to another. [#3454](https://github.com/MakieOrg/Makie.jl/pull/3454)
- Fixed bug in GLMakie where the update from a (i, j) sized GPU buffer to a (j, i) sized buffer would fail [#3456](https://github.com/MakieOrg/Makie.jl/pull/3456).

## 0.20.2
Expand Down
49 changes: 28 additions & 21 deletions src/basic_recipes/tooltip.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Creates a tooltip pointing at `position` displaying the given `string`
transparency = false,
visible = true,
inspectable = false,
space = :data,

# Text
textpadding = (4, 4, 4, 4), # LRBT
Expand Down Expand Up @@ -81,15 +82,21 @@ end

function plot!(p::Tooltip{<:Tuple{<:VecTypes}})
# TODO align

scene = parent_scene(p)
px_pos = map(scene.camera.projectionview, scene.camera.resolution, p[1]) do _, _, p
project(scene, p)
px_pos = map(
p, p[1], scene.camera.projectionview, p.model, transform_func(p),
p.space, scene.viewport) do pos, _, model, tf, space, viewport

# Adjusted from error_and_rangebars
spvm = clip_to_space(scene.camera, :pixel) * space_to_clip(scene.camera, space) * model
transformed = apply_transform(tf, pos, space)
p4d = spvm * to_ndim(Point4f, to_ndim(Point3f, transformed, 0), 1)
return Point3f(p4d) / p4d[4]
end

# Text

textpadding = map(p.textpadding) do pad
textpadding = map(p, p.textpadding) do pad
if pad isa Real
return (pad, pad, pad, pad)
elseif length(pad) == 4
Expand All @@ -100,7 +107,7 @@ function plot!(p::Tooltip{<:Tuple{<:VecTypes}})
end
end

text_offset = map(p.offset, textpadding, p.triangle_size, p.placement, p.align) do o, pad, ts, placement, align
text_offset = map(p, p.offset, textpadding, p.triangle_size, p.placement, p.align) do o, pad, ts, placement, align
l, r, b, t = pad

if placement === :left
Expand All @@ -117,7 +124,7 @@ function plot!(p::Tooltip{<:Tuple{<:VecTypes}})
end
end

text_align = map(p.placement, p.align) do placement, align
text_align = map(p, p.placement, p.align) do placement, align
if placement === :left
return (1.0, align)
elseif placement === :right
Expand All @@ -139,17 +146,17 @@ function plot!(p::Tooltip{<:Tuple{<:VecTypes}})
strokewidth = p.strokewidth, strokecolor = p.strokecolor,
transparency = p.transparency, visible = p.visible,
overdraw = p.overdraw, depth_shift = p.depth_shift,
inspectable = p.inspectable, space = :pixel
inspectable = p.inspectable, space = :pixel, transformation = Transformation()
)
translate!(tp, 0, 0, 1)

# TODO react to glyphcollection instead
bbox = map(
px_pos, p.text, text_align, text_offset, textpadding, p.align
p, px_pos, p.text, text_align, text_offset, textpadding, p.align
) do p, s, _, o, pad, align
bb = Rect2f(boundingbox(tp)) + o
bb = boundingbox(tp) + to_ndim(Vec3f, o, 0)
l, r, b, t = pad
return Rect2f(origin(bb) .- (l, b), widths(bb) .+ (l+r, b+t))
return Rect3f(origin(bb) .- (l, b, 0), widths(bb) .+ (l+r, b+t, 0))
end

# Text background mesh
Expand All @@ -159,7 +166,7 @@ function plot!(p::Tooltip{<:Tuple{<:VecTypes}})
color = p.backgroundcolor, fxaa = false,
transparency = p.transparency, visible = p.visible,
overdraw = p.overdraw, depth_shift = p.depth_shift,
inspectable = p.inspectable
inspectable = p.inspectable, transformation = Transformation()
)

# Triangle mesh
Expand All @@ -174,36 +181,36 @@ function plot!(p::Tooltip{<:Tuple{<:VecTypes}})
color = p.backgroundcolor,
transparency = p.transparency, visible = p.visible,
overdraw = p.overdraw, depth_shift = p.depth_shift,
inspectable = p.inspectable
inspectable = p.inspectable, transformation = Transformation()
)
onany(bbox, p.triangle_size, p.placement, p.align) do bb, s, placement, align
onany(p, bbox, p.triangle_size, p.placement, p.align) do bb, s, placement, align
o = origin(bb); w = widths(bb)
scale!(mp, s, s, s)

if placement === :left
translate!(mp, Vec3f(o[1] + w[1], o[2] + align * w[2], 0))
translate!(mp, Vec3f(o[1] + w[1], o[2] + align * w[2], o[3]))
rotate!(mp, qrotation(Vec3f(0,0,1), 0.5pi))
elseif placement === :right
translate!(mp, Vec3f(o[1], o[2] + align * w[2], 0))
rotate!(mp, qrotation(Vec3f(0,0,1), -0.5pi))
elseif placement in (:below, :down, :bottom)
translate!(mp, Vec3f(o[1] + align * w[1], o[2] + w[2], 0))
translate!(mp, Vec3f(o[1] + align * w[1], o[2] + w[2], o[3]))
rotate!(mp, Quaternionf(0,0,1,0)) # pi
elseif placement in (:above, :up, :top)
translate!(mp, Vec3f(o[1] + align * w[1], o[2], 0))
translate!(mp, Vec3f(o[1] + align * w[1], o[2], o[3]))
rotate!(mp, Quaternionf(0,0,0,1)) # 0
else
@error "Tooltip placement $placement invalid. Assuming :above"
translate!(mp, Vec3f(o[1] + align * w[1], o[2], 0))
translate!(mp, Vec3f(o[1] + align * w[1], o[2], o[3]))
rotate!(mp, Quaternionf(0,0,0,1))
end
return
end

# Outline

outline = map(bbox, p.triangle_size, p.placement, p.align) do bb, s, placement, align
l, b = origin(bb); w, h = widths(bb)
outline = map(p, bbox, p.triangle_size, p.placement, p.align) do bb, s, placement, align
l, b, z = origin(bb); w, h, _ = widths(bb)
r, t = (l, b) .+ (w, h)

# We start/end at half width/height here to avoid corners like this:
Expand Down Expand Up @@ -255,7 +262,7 @@ function plot!(p::Tooltip{<:Tuple{<:VecTypes}})
]
end

return shift
return to_ndim.(Vec3f, shift, z)
end

lines!(
Expand All @@ -264,7 +271,7 @@ function plot!(p::Tooltip{<:Tuple{<:VecTypes}})
linewidth = p.outline_linewidth, linestyle = p.outline_linestyle,
transparency = p.transparency, visible = p.visible,
overdraw = p.overdraw, depth_shift = p.depth_shift,
inspectable = p.inspectable
inspectable = p.inspectable, transformation = Transformation()
)

notify(p[1])
Expand Down
27 changes: 16 additions & 11 deletions src/interaction/inspector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,12 @@ end

# clears temporary plots (i.e. bboxes) and update selection
function clear_temporary_plots!(inspector::DataInspector, plot)
inspector.selection = plot
if inspector.selection !== plot
if haskey(inspector.selection, :inspector_clear)
inspector.selection[:inspector_clear][](inspector, inspector.selection)
end
inspector.selection = plot
end

for i in length(inspector.obsfuncs):-1:3
off(pop!(inspector.obsfuncs))
Expand Down Expand Up @@ -422,8 +427,8 @@ function show_data(inspector::DataInspector, plot::Scatter, idx)
tt = inspector.plot
scene = parent_scene(plot)

pos = position_on_plot(plot, idx)
proj_pos = shift_project(scene, pos)
pos = position_on_plot(plot, idx, apply_transform = false)
proj_pos = shift_project(scene, apply_transform_and_model(plot, pos))
update_tooltip_alignment!(inspector, proj_pos)

if haskey(plot, :inspector_label)
Expand Down Expand Up @@ -489,8 +494,8 @@ function show_data(inspector::DataInspector, plot::MeshScatter, idx)
a.indicator_visible[] = true
end

pos = position_on_plot(plot, idx)
proj_pos = shift_project(scene, pos)
pos = position_on_plot(plot, idx, apply_transform = false)
proj_pos = shift_project(scene, apply_transform_and_model(plot, pos))
update_tooltip_alignment!(inspector, proj_pos)

if haskey(plot, :inspector_label)
Expand All @@ -510,8 +515,8 @@ function show_data(inspector::DataInspector, plot::Union{Lines, LineSegments}, i
scene = parent_scene(plot)

# cast ray from cursor into screen, find closest point to line
pos = position_on_plot(plot, idx)
proj_pos = shift_project(scene, pos)
pos = position_on_plot(plot, idx, apply_transform = false)
proj_pos = shift_project(scene, apply_transform_and_model(plot, pos))
update_tooltip_alignment!(inspector, proj_pos)

tt.offset[] = ifelse(
Expand Down Expand Up @@ -596,7 +601,7 @@ function show_data(inspector::DataInspector, plot::Surface, idx)
proj_pos = Point2f(mouseposition_px(inspector.root))
update_tooltip_alignment!(inspector, proj_pos)

pos = position_on_plot(plot, idx)
pos = position_on_plot(plot, idx, apply_transform = false)

if !isnan(pos)
tt[1][] = proj_pos
Expand Down Expand Up @@ -810,8 +815,8 @@ function show_data(inspector::DataInspector, plot::BarPlot, idx)
tt = inspector.plot
scene = parent_scene(plot)

pos = apply_transform_and_model(plot, plot[1][][idx])
proj_pos = shift_project(scene, to_ndim(Point3f, pos, 0))
pos = plot[1][][idx]
proj_pos = shift_project(scene, apply_transform_and_model(plot, to_ndim(Point3f, pos, 0)))
update_tooltip_alignment!(inspector, proj_pos)

if a.enable_indicators[]
Expand Down Expand Up @@ -852,7 +857,7 @@ end
function show_data(inspector::DataInspector, plot::Arrows, idx, source)
a = inspector.attributes
tt = inspector.plot
pos = apply_transform_and_model(plot, plot[1][][idx])
pos = plot[1][][idx]

mpos = Point2f(mouseposition_px(inspector.root))
update_tooltip_alignment!(inspector, mpos)
Expand Down

0 comments on commit d11b786

Please sign in to comment.