Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the selection/hover behavior for plots #5096

Merged
merged 2 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions crates/re_space_view_time_series/src/space_view_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,8 @@ It can greatly improve performance (and readability) in such situations as it pr

let mut plot_item_id_to_entity_path = HashMap::default();

let mut is_resetting = false;

let egui_plot::PlotResponse {
inner: _,
response,
Expand All @@ -444,7 +446,7 @@ It can greatly improve performance (and readability) in such situations as it pr

let range_was_edited = state.last_range != y_range;
state.last_range = y_range;
let is_resetting = plot_ui.response().double_clicked();
is_resetting = plot_ui.response().double_clicked();
let current_auto = plot_ui.auto_bounds();

if let Some(y_range) = y_range {
Expand Down Expand Up @@ -529,17 +531,26 @@ It can greatly improve performance (and readability) in such situations as it pr
})
.map(|x| transform.position_from_point(&PlotPoint::new(x, 0.0)).x);

// Interact with the plot items (lines, scatters, etc.)
if let Some(entity_path) = hovered_plot_item
.and_then(|hovered_plot_item| plot_item_id_to_entity_path.get(&hovered_plot_item))
{
ctx.select_hovered_on_click(
&response,
re_viewer_context::Item::InstancePath(
Some(query.space_view_id),
entity_path.clone().into(),
),
);
// If we are not resetting on this frame, interact with the plot items (lines, scatters, etc.)
if !is_resetting {
if let Some(hovered) = hovered_plot_item
.and_then(|hovered_plot_item| plot_item_id_to_entity_path.get(&hovered_plot_item))
.map(|entity_path| {
re_viewer_context::Item::InstancePath(
Some(query.space_view_id),
entity_path.clone().into(),
)
})
.or_else(|| {
if response.hovered() {
Some(re_viewer_context::Item::SpaceView(query.space_view_id))
} else {
None
}
})
{
ctx.select_hovered_on_click(&response, hovered);
}
}

if let Some(mut time_x) = time_x {
Expand Down
96 changes: 96 additions & 0 deletions tests/python/release_checklist/check_hover_select_reset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from __future__ import annotations

import os
from argparse import Namespace
from uuid import uuid4

import rerun as rr

README = """
# Hover, Select, and Reset

This checks whether different UIs behave correctly with hover and selection.

### Hover
For each of the views:
* Hover the view and verify it shows up as highlighted in the blueprint tree.
* Hover the entity and verify it shows up highlighted in the blueprint tree.
* For 2D and 3D views the entity itself should be outlined and show a hover element.
* For plot view, the line-series will not highlight, but the plot should show info about the point.

### 2D/3D Select
For each of the views:
* Click on the background of the view, and verify the view becomes selected.
* Click on an entity, and verify the it becomes selected.
* For 2D and 3D views the selected instance will not be visible in the blueprint tree.
* If you think this is unexpected, create an issue.
* Double-click the entity and verify that it becomes selected and highlighted in the blueprint tree.

### Reset
For each of the views:
* Zoom and/or pan the view
* Double-click the background of the view and verify it resets the view to its default state.
"""


def log_readme() -> None:
rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True)


def log_plots() -> None:
from math import cos, sin, tau

rr.log("plots/cos", rr.SeriesPoint())

for t in range(0, int(tau * 2 * 10.0)):
rr.set_time_sequence("frame_nr", t)

sin_of_t = sin(float(t) / 10.0)
rr.log("plots/sin", rr.Scalar(sin_of_t))

cos_of_t = cos(float(t) / 10.0)
rr.log("plots/cos", rr.Scalar(cos_of_t))


def log_points_3d() -> None:
from numpy.random import default_rng

rng = default_rng(12345)

positions = rng.uniform(-5, 5, size=[10, 3])
colors = rng.uniform(0, 255, size=[10, 3])
radii = rng.uniform(0, 1, size=[10])

rr.log("3d/points", rr.Points3D(positions, colors=colors, radii=radii))


def log_points_2d() -> None:
from numpy.random import default_rng

rng = default_rng(12345)

positions = rng.uniform(-5, 5, size=[10, 2])
colors = rng.uniform(0, 255, size=[10, 3])
radii = rng.uniform(0, 1, size=[10])

rr.log("2d/points", rr.Points2D(positions, colors=colors, radii=radii))


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
log_plots()
log_points_3d()
log_points_2d()


if __name__ == "__main__":
import argparse

parser = argparse.ArgumentParser(description="Interactive release checklist")
rr.script_add_args(parser)
args = parser.parse_args()
run(args)
Loading