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:
Dustin Carlino 2020-06-18 12:44:47 -07:00
parent bc8f352600
commit b5e9d64a9b
3 changed files with 174 additions and 135 deletions

View File

@ -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

View File

@ -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();
}

View File

@ -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");