mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 07:52:05 +03:00
optionally use arrow keys to pan the map. need this for filming a trailer. fixes #10. also make the settings panel layout less horrific
This commit is contained in:
parent
bc8f352600
commit
b5e9d64a9b
@ -114,7 +114,7 @@ Constructing the map:
|
||||
- `map_model`: the final representation of the map, also conversion from the
|
||||
intermediate map format into the final format
|
||||
- `map_editor`: GUI for modifying geometry of maps and creating maps from
|
||||
scratch
|
||||
scratch. pretty abandoned as of June 2020
|
||||
- `importer`: tool to run the entire import pipeline
|
||||
- `updater`: tool to download/upload large files used in the import pipeline
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::assets::Assets;
|
||||
use crate::{ScreenDims, ScreenPt, ScreenRectangle, UserInput};
|
||||
use crate::{hotkey, Key, ScreenDims, ScreenPt, ScreenRectangle, UserInput};
|
||||
use abstutil::Timer;
|
||||
use geom::{Bounds, Pt2D};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -37,6 +37,7 @@ pub struct Canvas {
|
||||
pub invert_scroll: bool,
|
||||
pub touchpad_to_move: bool,
|
||||
pub edge_auto_panning: bool,
|
||||
pub keys_to_pan: bool,
|
||||
|
||||
// TODO Bit weird and hacky to mutate inside of draw() calls.
|
||||
pub(crate) covered_areas: RefCell<Vec<ScreenRectangle>>,
|
||||
@ -67,6 +68,7 @@ impl Canvas {
|
||||
invert_scroll: false,
|
||||
touchpad_to_move: false,
|
||||
edge_auto_panning: false,
|
||||
keys_to_pan: false,
|
||||
|
||||
covered_areas: RefCell::new(Vec::new()),
|
||||
|
||||
@ -87,19 +89,7 @@ impl Canvas {
|
||||
if self.touchpad_to_move {
|
||||
if let Some((scroll_x, scroll_y)) = input.get_mouse_scroll() {
|
||||
if self.lctrl_held {
|
||||
let old_zoom = self.cam_zoom;
|
||||
// By popular request, some limits ;)
|
||||
self.cam_zoom = 1.1_f64
|
||||
.powf(old_zoom.log(1.1) + scroll_y)
|
||||
.max(self.min_zoom())
|
||||
.min(150.0);
|
||||
|
||||
// Make screen_to_map of cursor_{x,y} still point to the same thing after
|
||||
// zooming.
|
||||
self.cam_x = ((self.cam_zoom / old_zoom) * (self.cursor_x + self.cam_x))
|
||||
- self.cursor_x;
|
||||
self.cam_y = ((self.cam_zoom / old_zoom) * (self.cursor_y + self.cam_y))
|
||||
- self.cursor_y;
|
||||
self.zoom(scroll_y, (self.cursor_x, self.cursor_y));
|
||||
} else {
|
||||
// Woo, inversion is different for the two. :P
|
||||
self.cam_x += scroll_x * PAN_SPEED;
|
||||
@ -112,19 +102,28 @@ impl Canvas {
|
||||
}
|
||||
|
||||
if let Some((_, scroll)) = input.get_mouse_scroll() {
|
||||
let old_zoom = self.cam_zoom;
|
||||
// By popular request, some limits ;)
|
||||
self.cam_zoom = 1.1_f64
|
||||
.powf(old_zoom.log(1.1) + scroll)
|
||||
.max(self.min_zoom())
|
||||
.min(150.0);
|
||||
self.zoom(scroll, (self.cursor_x, self.cursor_y));
|
||||
}
|
||||
}
|
||||
|
||||
// Make screen_to_map of cursor_{x,y} still point to the same thing after
|
||||
// zooming.
|
||||
self.cam_x =
|
||||
((self.cam_zoom / old_zoom) * (self.cursor_x + self.cam_x)) - self.cursor_x;
|
||||
self.cam_y =
|
||||
((self.cam_zoom / old_zoom) * (self.cursor_y + self.cam_y)) - self.cursor_y;
|
||||
if self.keys_to_pan {
|
||||
if input.new_was_pressed(&hotkey(Key::LeftArrow).unwrap()) {
|
||||
self.cam_x -= PAN_SPEED;
|
||||
}
|
||||
if input.new_was_pressed(&hotkey(Key::RightArrow).unwrap()) {
|
||||
self.cam_x += PAN_SPEED;
|
||||
}
|
||||
if input.new_was_pressed(&hotkey(Key::UpArrow).unwrap()) {
|
||||
self.cam_y -= PAN_SPEED;
|
||||
}
|
||||
if input.new_was_pressed(&hotkey(Key::DownArrow).unwrap()) {
|
||||
self.cam_y += PAN_SPEED;
|
||||
}
|
||||
if input.new_was_pressed(&hotkey(Key::Q).unwrap()) {
|
||||
self.zoom(1.0, (self.window_width / 2.0, self.window_height / 2.0));
|
||||
}
|
||||
if input.new_was_pressed(&hotkey(Key::W).unwrap()) {
|
||||
self.zoom(-1.0, (self.window_width / 2.0, self.window_height / 2.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,8 +149,8 @@ impl Canvas {
|
||||
let cursor_map_pt = self.screen_to_map(self.get_cursor());
|
||||
let inner_bounds = self.get_inner_bounds();
|
||||
let map_bounds = self.get_map_bounds();
|
||||
if !inner_bounds.contains(cursor_screen_pt)
|
||||
&& self.edge_auto_panning
|
||||
if self.edge_auto_panning
|
||||
&& !inner_bounds.contains(cursor_screen_pt)
|
||||
&& map_bounds.contains(cursor_map_pt)
|
||||
{
|
||||
let center_pt = self.center_to_screen_pt().to_pt();
|
||||
@ -161,13 +160,27 @@ impl Canvas {
|
||||
f64::sqrt(displacement_x.powf(2.0) + displacement_y.powf(2.0));
|
||||
let displacement_unit_x = displacement_x / displacement_magnitude;
|
||||
let displacement_unit_y = displacement_y / displacement_magnitude;
|
||||
//Add displacement along each axis
|
||||
// Add displacement along each axis
|
||||
self.cam_x += displacement_unit_x * PAN_SPEED;
|
||||
self.cam_y += displacement_unit_y * PAN_SPEED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn zoom(&mut self, delta: f64, focus: (f64, f64)) {
|
||||
let old_zoom = self.cam_zoom;
|
||||
// By popular request, some limits ;)
|
||||
self.cam_zoom = 1.1_f64
|
||||
.powf(old_zoom.log(1.1) + delta)
|
||||
.max(self.min_zoom())
|
||||
.min(150.0);
|
||||
|
||||
// Make screen_to_map of the focus point still point to the same thing after
|
||||
// zooming.
|
||||
self.cam_x = ((self.cam_zoom / old_zoom) * (focus.0 + self.cam_x)) - focus.0;
|
||||
self.cam_y = ((self.cam_zoom / old_zoom) * (focus.1 + self.cam_y)) - focus.1;
|
||||
}
|
||||
|
||||
pub(crate) fn start_drawing(&self) {
|
||||
self.covered_areas.borrow_mut().clear();
|
||||
}
|
||||
|
@ -52,123 +52,146 @@ impl OptionsPanel {
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("Settings").small_heading().draw(ctx),
|
||||
Btn::text_fg("X")
|
||||
Btn::plaintext("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
.align_right(),
|
||||
]),
|
||||
Checkbox::text(ctx, "Enable developer mode", None, app.opts.dev).margin(5),
|
||||
Checkbox::text(
|
||||
ctx,
|
||||
"Invert direction of vertical scrolling",
|
||||
None,
|
||||
ctx.canvas.invert_scroll,
|
||||
)
|
||||
.margin(5),
|
||||
Checkbox::text(
|
||||
ctx,
|
||||
"Enable panning map when cursor is at edge of screen",
|
||||
None,
|
||||
ctx.canvas.edge_auto_panning,
|
||||
)
|
||||
.named("disable pan"),
|
||||
Checkbox::text(
|
||||
ctx,
|
||||
"Use touchpad to pan and hold Control to zoom",
|
||||
None,
|
||||
ctx.canvas.touchpad_to_move,
|
||||
)
|
||||
.margin(5),
|
||||
Widget::row(vec![
|
||||
"Traffic signal rendering:".draw_text(ctx).margin(5),
|
||||
Widget::dropdown(
|
||||
])
|
||||
.margin_below(10),
|
||||
Checkbox::text(ctx, "Enable developer mode", None, app.opts.dev)
|
||||
.margin_below(10),
|
||||
"Camera controls".draw_text(ctx).margin_below(10),
|
||||
Widget::col(vec![
|
||||
Checkbox::text(
|
||||
ctx,
|
||||
"Traffic signal rendering",
|
||||
app.opts.traffic_signal_style.clone(),
|
||||
vec![
|
||||
Choice::new(
|
||||
"Brian's variation of arrows showing the protected and \
|
||||
permitted movements",
|
||||
TrafficSignalStyle::BAP,
|
||||
),
|
||||
Choice::new(
|
||||
"arrows showing the protected and permitted movements",
|
||||
TrafficSignalStyle::GroupArrows,
|
||||
),
|
||||
Choice::new(
|
||||
"arrows showing the protected and permitted movements, with \
|
||||
sidewalks",
|
||||
TrafficSignalStyle::Sidewalks,
|
||||
),
|
||||
Choice::new(
|
||||
"icons for movements (like the editor UI)",
|
||||
TrafficSignalStyle::Icons,
|
||||
),
|
||||
Choice::new(
|
||||
"arrows showing individual turns (to debug)",
|
||||
TrafficSignalStyle::IndividualTurnArrows,
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
Widget::row(vec![
|
||||
"Color scheme:".draw_text(ctx).margin(5),
|
||||
Widget::dropdown(
|
||||
ctx,
|
||||
"Color scheme",
|
||||
app.opts.color_scheme,
|
||||
ColorSchemeChoice::choices(),
|
||||
),
|
||||
]),
|
||||
Widget::row(vec![
|
||||
format!(
|
||||
"Scale factor for text / UI elements (your monitor is {}):",
|
||||
ctx.monitor_scale_factor()
|
||||
"Invert direction of vertical scrolling",
|
||||
None,
|
||||
ctx.canvas.invert_scroll,
|
||||
)
|
||||
.draw_text(ctx)
|
||||
.margin(5),
|
||||
Widget::dropdown(
|
||||
.margin_below(10),
|
||||
Checkbox::text(
|
||||
ctx,
|
||||
"Scale factor",
|
||||
ctx.get_scale_factor(),
|
||||
vec![
|
||||
Choice::new("0.5", 0.5),
|
||||
Choice::new("1.0", 1.0),
|
||||
Choice::new("1.5", 1.5),
|
||||
Choice::new("2.0", 2.0),
|
||||
],
|
||||
"Pan map when cursor is at edge of screen",
|
||||
None,
|
||||
ctx.canvas.edge_auto_panning,
|
||||
)
|
||||
.named("autopan")
|
||||
.margin_below(10),
|
||||
Checkbox::text(
|
||||
ctx,
|
||||
"Use touchpad to pan and hold Control to zoom",
|
||||
None,
|
||||
ctx.canvas.touchpad_to_move,
|
||||
)
|
||||
.margin_below(10),
|
||||
Checkbox::text(
|
||||
ctx,
|
||||
"Use arrow keys to pan and Q/W to zoom",
|
||||
None,
|
||||
ctx.canvas.keys_to_pan,
|
||||
),
|
||||
]),
|
||||
Widget::row(vec![
|
||||
"Camera zoom to switch to unzoomed view"
|
||||
])
|
||||
.bg(app.cs.section_bg)
|
||||
.padding(8)
|
||||
.margin_below(10),
|
||||
"Appearance".draw_text(ctx).margin_below(10),
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
"Traffic signal rendering:".draw_text(ctx).margin_right(15),
|
||||
Widget::dropdown(
|
||||
ctx,
|
||||
"Traffic signal rendering",
|
||||
app.opts.traffic_signal_style.clone(),
|
||||
vec![
|
||||
Choice::new(
|
||||
"Brian's variation of arrows showing the protected and \
|
||||
permitted movements",
|
||||
TrafficSignalStyle::BAP,
|
||||
),
|
||||
Choice::new(
|
||||
"arrows showing the protected and permitted movements",
|
||||
TrafficSignalStyle::GroupArrows,
|
||||
),
|
||||
Choice::new(
|
||||
"arrows showing the protected and permitted movements, \
|
||||
with sidewalks",
|
||||
TrafficSignalStyle::Sidewalks,
|
||||
),
|
||||
Choice::new(
|
||||
"icons for movements (like the editor UI)",
|
||||
TrafficSignalStyle::Icons,
|
||||
),
|
||||
Choice::new(
|
||||
"arrows showing individual turns (to debug)",
|
||||
TrafficSignalStyle::IndividualTurnArrows,
|
||||
),
|
||||
],
|
||||
),
|
||||
])
|
||||
.margin_below(10),
|
||||
Widget::row(vec![
|
||||
"Color scheme:".draw_text(ctx).margin_right(5),
|
||||
Widget::dropdown(
|
||||
ctx,
|
||||
"Color scheme",
|
||||
app.opts.color_scheme,
|
||||
ColorSchemeChoice::choices(),
|
||||
),
|
||||
])
|
||||
.margin_below(10),
|
||||
Widget::row(vec![
|
||||
format!(
|
||||
"Scale factor for text / UI elements (your monitor is {}):",
|
||||
ctx.monitor_scale_factor()
|
||||
)
|
||||
.draw_text(ctx)
|
||||
.margin(5),
|
||||
Widget::dropdown(
|
||||
.margin_right(15),
|
||||
Widget::dropdown(
|
||||
ctx,
|
||||
"Scale factor",
|
||||
ctx.get_scale_factor(),
|
||||
vec![
|
||||
Choice::new("0.5", 0.5),
|
||||
Choice::new("1.0", 1.0),
|
||||
Choice::new("1.5", 1.5),
|
||||
Choice::new("2.0", 2.0),
|
||||
],
|
||||
),
|
||||
])
|
||||
.margin_below(10),
|
||||
Widget::row(vec![
|
||||
"Camera zoom to switch to unzoomed view"
|
||||
.draw_text(ctx)
|
||||
.margin_right(15),
|
||||
Widget::dropdown(
|
||||
ctx,
|
||||
"min zoom",
|
||||
app.opts.min_zoom_for_detail,
|
||||
vec![
|
||||
Choice::new("1.0", 1.0),
|
||||
Choice::new("2.0", 2.0),
|
||||
Choice::new("3.0", 3.0),
|
||||
Choice::new("4.0", 4.0),
|
||||
Choice::new("5.0", 5.0),
|
||||
Choice::new("6.0", 6.0),
|
||||
],
|
||||
),
|
||||
])
|
||||
.margin_below(10),
|
||||
Checkbox::text(
|
||||
ctx,
|
||||
"min zoom",
|
||||
app.opts.min_zoom_for_detail,
|
||||
vec![
|
||||
Choice::new("1.0", 1.0),
|
||||
Choice::new("2.0", 2.0),
|
||||
Choice::new("3.0", 3.0),
|
||||
Choice::new("4.0", 4.0),
|
||||
Choice::new("5.0", 5.0),
|
||||
Choice::new("6.0", 6.0),
|
||||
],
|
||||
"Draw enlarged unzoomed agents",
|
||||
None,
|
||||
app.opts.large_unzoomed_agents,
|
||||
),
|
||||
]),
|
||||
Checkbox::text(
|
||||
ctx,
|
||||
"Draw enlarged unzoomed agents",
|
||||
None,
|
||||
app.opts.large_unzoomed_agents,
|
||||
)
|
||||
.margin(5),
|
||||
])
|
||||
.bg(app.cs.section_bg)
|
||||
.padding(8)
|
||||
.margin_below(10),
|
||||
Btn::text_bg2("Apply")
|
||||
.build_def(ctx, hotkey(Key::Enter))
|
||||
.margin(5)
|
||||
.centered_horiz(),
|
||||
])
|
||||
.padding(10)
|
||||
.padding(16)
|
||||
.bg(app.cs.panel_bg),
|
||||
)
|
||||
.build(ctx),
|
||||
@ -190,7 +213,10 @@ impl State for OptionsPanel {
|
||||
ctx.canvas.touchpad_to_move = self
|
||||
.composite
|
||||
.is_checked("Use touchpad to pan and hold Control to zoom");
|
||||
ctx.canvas.edge_auto_panning = self.composite.is_checked("disable pan");
|
||||
ctx.canvas.keys_to_pan = self
|
||||
.composite
|
||||
.is_checked("Use arrow keys to pan and Q/W to zoom");
|
||||
ctx.canvas.edge_auto_panning = self.composite.is_checked("autopan");
|
||||
app.opts.dev = self.composite.is_checked("Enable developer mode");
|
||||
|
||||
let style = self.composite.dropdown_value("Traffic signal rendering");
|
||||
|
Loading…
Reference in New Issue
Block a user