feat(plot): the figure crosshair marks the hovered row, and the stroke is thin, dashed and configurable
This commit is contained in:
1 parent
cae672bc99
commit
eee7c34dd5
12 files changed
+166
-12
No files matched your search
+13
-4
@@ -568,7 +568,7 @@ void Renderer::upload_text_vertices(std::span<const f32> interleaved) noexcept {
|
||||
text_vao_.upload(interleaved.data(), static_cast<u32>(interleaved.size() / 6u));
|
||||
}
|
||||
|
||||
void Renderer::flush_lines(const Mapping& map, Color color, f32 width) noexcept {
|
||||
void Renderer::flush_lines(const Mapping& map, Color color, f32 width, Vec2 dash) noexcept {
|
||||
const u32 segments = lines_.segment_count();
|
||||
if (segments != 0 && ready_) {
|
||||
upload_vertices(lines_.data());
|
||||
@@ -577,6 +577,9 @@ void Renderer::flush_lines(const Mapping& map, Color color, f32 width) noexcept
|
||||
line_program_.set_offset(map.offset);
|
||||
line_program_.set_viewport({viewport_.w, viewport_.h});
|
||||
line_program_.set_width(width);
|
||||
// Set on *every* flush, solid included, so the crosshair's dash cannot leak into the
|
||||
// grid, a trace or a cursor drawn after it (see draw_crosshair_lines()).
|
||||
line_program_.set_dash(dash);
|
||||
line_program_.set_color(color);
|
||||
line_vao_.bind();
|
||||
// One triangle strip per instance, four corners from gl_VertexID.
|
||||
@@ -1192,25 +1195,31 @@ void Renderer::draw_crosshair_lines(const Plot& plot, const PlotLayout& layout)
|
||||
const CrosshairLayout& crosshair = layout.crosshair;
|
||||
if (crosshair.empty()) return;
|
||||
|
||||
const f32 stroke = style_.device(style_.line_width_px);
|
||||
// The stroke and dash the layout already resolved from the crosshair's own override and the
|
||||
// global style, in device pixels -- one source, so the boxes the layout held inside `axes` and
|
||||
// the strokes drawn here cannot disagree (spec §17).
|
||||
const f32 stroke = crosshair.stroke;
|
||||
// The two lines. Each is staged as one data-space segment at the *centre* of the stroke box
|
||||
// the layout placed, spanning that box's own extent, so the pixels this draws are the box
|
||||
// rather than a second placement of the same rule: the layout held the box inside `axes`,
|
||||
// and the clip keeps the half pixel the rasteriser puts outside the box's fractional edges.
|
||||
//
|
||||
// The dash rides on the same segment: `v_along` is measured from the axes edge the line is
|
||||
// staged from, so no geometry is added and the phase does not depend on the transform.
|
||||
const Mapping data = mapping(plot, 0u, 0u);
|
||||
if (crosshair.vertical.w > 0.0f) {
|
||||
const f64 x = plot.x_transform(0u).to_data_x(
|
||||
static_cast<f64>(crosshair.vertical.x + 0.5f * crosshair.vertical.w));
|
||||
const Range y_range = plot.y_range(0u);
|
||||
stage_segment(x, y_range.min, x, y_range.max, plot.x_axis(0u).log, plot.y_axis(0u).log);
|
||||
flush_lines(data, style_.crosshair, stroke);
|
||||
flush_lines(data, style_.crosshair, stroke, crosshair.dash);
|
||||
}
|
||||
if (crosshair.horizontal.h > 0.0f) {
|
||||
const f64 y = plot.y_transform(0u).to_data_y(
|
||||
static_cast<f64>(crosshair.horizontal.y + 0.5f * crosshair.horizontal.h));
|
||||
const Range x_range = plot.x_range(0u);
|
||||
stage_segment(x_range.min, y, x_range.max, y, plot.x_axis(0u).log, plot.y_axis(0u).log);
|
||||
flush_lines(data, style_.crosshair, stroke);
|
||||
flush_lines(data, style_.crosshair, stroke, crosshair.dash);
|
||||
}
|
||||
|
||||
// A small cross at each trace's intersection, in the trace's own colour -- opaque, like a
|
||||
|
||||
Reference in new issue
Block a user