Skip to content

Commit

Permalink
feat!: use shitf+right click for scaling x-axes
Browse files Browse the repository at this point in the history
Before, this required an extra mode (pressing "s") which
is now removed.
  • Loading branch information
carrascomj committed Jan 16, 2025
1 parent ca98f35 commit 3d3426d
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 90 deletions.
9 changes: 5 additions & 4 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ Controls

* **Left click** and drag to move around the map.
* **Scroll whell** to zoom in and out.
* **Right click** on a histogram or the legend (on its center) and drag the mouse while holding
the button to zoom in/out to rotate it. On axis mode, scale the axis instead.
* **Middle click** on a histogram or the legend (on its center) and drag the mouse while holding
the button to move it.
* **Right click** on a histogram or the legend (on its center) and drag the mouse while holding
the button to zoom in/out to rotate it.
* **Right click + Shift** on a histogram (on its center) and drag the mouse while holding
the button to scale the x-axis of the histogram.
* :code:`+` and :code:`-` keys to scale up and down the legend. If :code:`Control` is pressed,
the Settings are scale
* :code:`s` to toggle axis mode, which shows the histogram axes and allows for scaling them.
the Settings are scale.
* The `Settings` window can be used to change the appeareance and export the map as a json or an image.

Contents
Expand Down
12 changes: 8 additions & 4 deletions src/funcplot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bevy::{
text::TextRoot,
};
use bevy_prototype_lyon::{
prelude::{GeometryBuilder, PathBuilder, Shape, Stroke},
prelude::{GeometryBuilder, PathBuilder, Shape, Stroke, StrokeOptions},
shapes,
};
use colorgrad::{Color as GradColor, CustomGradient, Gradient};
Expand Down Expand Up @@ -230,13 +230,17 @@ impl<T: TextRoot> ScaleBundle<T> {

pub fn plot_line(size: f32, transform: Transform) -> (Shape, Visibility, Transform, Stroke) {
let mut path_builder = PathBuilder::new();
path_builder.move_to(Vec2::new(-size / 2., 0.));
path_builder.line_to(Vec2::new(size / 2., 0.));
// with a small -5 offset in the y-axis
path_builder.move_to(Vec2::new(-size / 2., -5.));
path_builder.line_to(Vec2::new(size / 2., -5.));
(
GeometryBuilder::build_as(&path_builder.build()),
bevy::prelude::Visibility::Hidden,
transform,
Stroke::color(Color::BLACK),
Stroke {
options: StrokeOptions::default().with_line_width(2.0),
color: Color::linear_rgba(1.0, 0.0, 0.0, 0.7),
},
)
}

Expand Down
16 changes: 0 additions & 16 deletions src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ impl Plugin for GuiPlugin {
let building = app
.add_plugins(EguiPlugin)
.insert_resource(UiState::default())
.insert_resource(AxisMode::Hide)
.insert_resource(ActiveData::default())
.add_event::<SaveEvent>()
.add_systems(Update, ui_settings)
Expand All @@ -37,21 +36,6 @@ impl Plugin for GuiPlugin {
}
}

#[derive(Resource)]
pub enum AxisMode {
Show,
Hide,
}

impl AxisMode {
pub fn toggle(&mut self) {
match self {
AxisMode::Show => *self = AxisMode::Hide,
AxisMode::Hide => *self = AxisMode::Show,
}
}
}

/// Retrieve a mutable reference to the color or insert
/// * a random color with the alpha that is already in the map at the empty string; or
/// * the color at the empty string (random = false).
Expand Down
123 changes: 57 additions & 66 deletions src/picking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
use crate::escher::{ArrowTag, Hover, NodeToText, ARROW_COLOR};
use crate::geom::{AnyTag, Drag, HistTag, VisCondition, Xaxis};
use crate::gui::{AxisMode, UiState};
use crate::gui::UiState;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
use bevy_prototype_lyon::prelude::Shape;
use std::fmt::Debug;

const HIGH_COLOR: Color = Color::srgb(183. / 255., 210. / 255., 255.);
Expand All @@ -17,7 +16,7 @@ impl Plugin for PickingPlugin {
app.add_systems(Update, show_hover)
.add_systems(Update, follow_mouse_on_drag)
.add_systems(Update, rotate_or_scale_on_right_drag)
.add_systems(Update, show_axes)
.add_systems(Update, mouse_hover_highlight)
.add_systems(Update, mouse_click_system);
}
}
Expand All @@ -35,31 +34,23 @@ pub fn get_pos(win: &Window, camera: &Camera, camera_transform: &GlobalTransform
/// mechanism does not seem to work for non-UI nodes for some reason.
pub fn mouse_click_system(
mouse_button_input: Res<ButtonInput<MouseButton>>,
node_to_text: Res<NodeToText>,
axis_mode: Res<AxisMode>,
mut drag_query: Query<(&Transform, &mut Drag, &Xaxis), Without<Node>>,
mut text_query: Query<(&mut TextFont, &mut TextColor), With<ArrowTag>>,
key_input: Res<ButtonInput<KeyCode>>,
mut drag_query: Query<(&Transform, &mut Drag), (Without<Node>, With<Xaxis>)>,
windows: Query<(Entity, &Window), With<PrimaryWindow>>,
q_camera: Query<(&Camera, &GlobalTransform)>,
) {
let (camera, camera_transform) = q_camera.single();
let Ok((_, win)) = windows.get_single() else {
return;
};
if mouse_button_input.just_pressed(MouseButton::Middle) {
for (trans, mut drag, axis) in drag_query.iter_mut() {
let (camera, camera_transform) = q_camera.single();
let Ok((_, win)) = windows.get_single() else {
return;
};
for (trans, mut drag) in drag_query.iter_mut() {
if let Some(world_pos) = get_pos(win, camera, camera_transform) {
if (world_pos - Vec2::new(trans.translation.x, trans.translation.y))
.length_squared()
< 5000.
{
drag.dragged = true;
node_to_text.inner.get(&axis.node_id).map(|e| {
text_query.get_mut(*e).map(|mut text| {
text.0.font_size = 40.;
text.1 .0 = HIGH_COLOR;
})
});
// do not move more than one component at the same time
break;
}
Expand All @@ -68,53 +59,70 @@ pub fn mouse_click_system(
}

if mouse_button_input.just_released(MouseButton::Middle) {
for (_, mut drag, axis) in drag_query.iter_mut() {
for (_, mut drag) in drag_query.iter_mut() {
drag.dragged = false;
node_to_text.inner.get(&axis.node_id).map(|e| {
text_query.get_mut(*e).map(|mut text| {
text.0.font_size = 35.;
text.1 .0 = ARROW_COLOR;
})
});
}
}
if mouse_button_input.just_pressed(MouseButton::Right) {
for (trans, mut drag, axis) in drag_query.iter_mut() {
let (camera, camera_transform) = q_camera.single();
let Ok((_, win)) = windows.get_single() else {
return;
};
let scaling =
key_input.pressed(KeyCode::ShiftLeft) | key_input.pressed(KeyCode::ShiftRight);
for (trans, mut drag) in drag_query.iter_mut() {
if let Some(world_pos) = get_pos(win, camera, camera_transform) {
if (world_pos - Vec2::new(trans.translation.x, trans.translation.y))
.length_squared()
< 5000.
{
if matches!(*axis_mode, AxisMode::Show) {
drag.scaling = true;
} else {
drag.rotating = true;
}
node_to_text.inner.get(&axis.node_id).map(|e| {
text_query.get_mut(*e).map(|mut text| {
text.0.font_size = 40.;
text.1 .0 = HIGH_COLOR;
})
});
drag.scaling = scaling;
drag.rotating = !scaling;
// do not move more than one component at the same time
break;
}
}
}
}

if mouse_button_input.just_released(MouseButton::Right) {
for (_, mut drag, axis) in drag_query.iter_mut() {
drag.rotating = false;
for (_, mut drag) in drag_query.iter_mut() {
drag.scaling = false;
node_to_text.inner.get(&axis.node_id).map(|e| {
text_query.get_mut(*e).map(|mut text| {
text.0.font_size = 35.;
text.1 .0 = ARROW_COLOR;
})
});
drag.rotating = false;
}
}
}

pub fn mouse_hover_highlight(
node_to_text: Res<NodeToText>,
mut drag_query: Query<(&Transform, &mut Drag, &Xaxis, &mut Visibility), Without<Node>>,
mut text_query: Query<&mut TextColor, With<ArrowTag>>,
windows: Query<(Entity, &Window), With<PrimaryWindow>>,
q_camera: Query<(&Camera, &GlobalTransform)>,
) {
let (camera, camera_transform) = q_camera.single();
let Ok((_, win)) = windows.get_single() else {
return;
};
if let Some(world_pos) = get_pos(win, camera, camera_transform) {
for (trans, drag, axis, mut vis) in drag_query.iter_mut() {
let already_interacting = drag.scaling | drag.rotating | drag.dragged;
if ((world_pos - Vec2::new(trans.translation.x, trans.translation.y)).length_squared()
< 5000.)
| already_interacting
{
// on hover: show axis line and highlight reaction name
node_to_text.inner.get(&axis.node_id).map(|e| {
text_query.get_mut(*e).map(|mut color| {
color.0 = HIGH_COLOR;
})
});
*vis = Visibility::Visible;
break;
} else {
node_to_text.inner.get(&axis.node_id).map(|e| {
text_query.get_mut(*e).map(|mut color| {
color.0 = ARROW_COLOR;
})
});
*vis = Visibility::Hidden;
}
}
}
}
Expand Down Expand Up @@ -246,20 +254,3 @@ fn show_hover(
}
}
}
/// Show/hide axes of histograms when `s` is pressed.
fn show_axes(
key_input: Res<ButtonInput<KeyCode>>,
mut mode: ResMut<AxisMode>,
mut axis_query: Query<&mut Visibility, (With<Xaxis>, With<Shape>)>,
) {
if key_input.just_pressed(KeyCode::KeyS) {
mode.toggle();
axis_query.iter_mut().for_each(|mut v| {
*v = match *v {
Visibility::Inherited => Visibility::Inherited,
Visibility::Hidden => Visibility::Visible,
Visibility::Visible => Visibility::Hidden,
}
});
}
}

0 comments on commit 3d3426d

Please sign in to comment.