Skip to content

Commit

Permalink
Improve the selection/hover behavior for plots (#5096)
Browse files Browse the repository at this point in the history
### What
 - Resolves: #5090

Several changes to plots:
- When resetting the plot, don't trigger a selection. Previously if an
item ended up under the cursor **after** the reset, it would end up
selected.
- Additionally, when hovering/clicking the background of the plot,
process hover/selection accordingly.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/5096/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/5096/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/5096/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5096)
- [Docs
preview](https://rerun.io/preview/fa4f6d378ee0bde0a4de2b6caa3866b763145b0c/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/fa4f6d378ee0bde0a4de2b6caa3866b763145b0c/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
  • Loading branch information
jleibs authored Feb 7, 2024
1 parent 16c8737 commit 70b3dd8
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 12 deletions.
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)

0 comments on commit 70b3dd8

Please sign in to comment.