mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 07:52:05 +03:00
plumbing window_size with canvas
This commit is contained in:
parent
10dfceb4ec
commit
8f244438c1
@ -168,3 +168,17 @@ Traffic signals?
|
||||
- drawing turn icons as red/yellow/green is pretty clear...
|
||||
- could draw an unaligned signal box with 3 circles in the middle of the intersection, but what does it represent? maybe just an initial indicator of what's going on; not full detail.
|
||||
- similarly, draw a single stop sign in the middle of other intersections? :P
|
||||
|
||||
|
||||
|
||||
|
||||
GUI refactoring thoughts:
|
||||
- GfxCtx members should be private. make methods for drawing rectangles and such
|
||||
- should be useful short term. dunno how this will look later with gfx-rs, but dedupes code in the meantime.
|
||||
- should GfxCtx own Canvas or vice versa?
|
||||
- Canvas has persistent state, GfxCtx is ephemeral every draw cycle
|
||||
- dont want to draw outside of render, but may want to readjust camera
|
||||
- compromise is maybe storing the last known window size in canvas, so we dont have to keep plumbing it between frames anyway.
|
||||
|
||||
|
||||
should GfxCtx own canvas?
|
||||
|
@ -26,9 +26,9 @@ pub struct UI {
|
||||
}
|
||||
|
||||
impl UI {
|
||||
pub fn new() -> UI {
|
||||
pub fn new(window_size: Size) -> UI {
|
||||
UI {
|
||||
canvas: Canvas::new(),
|
||||
canvas: Canvas::new(window_size),
|
||||
p3_offset: (200.0, 150.0),
|
||||
show_labels: true,
|
||||
}
|
||||
@ -36,11 +36,7 @@ impl UI {
|
||||
}
|
||||
|
||||
impl gui::GUI for UI {
|
||||
fn event(
|
||||
mut self,
|
||||
input: &mut UserInput,
|
||||
_window_size: &Size,
|
||||
) -> (UI, animation::EventLoopMode) {
|
||||
fn event(mut self, input: &mut UserInput) -> (UI, animation::EventLoopMode) {
|
||||
if input.unimportant_key_pressed(Key::Escape, "Press escape to quit") {
|
||||
process::exit(0);
|
||||
}
|
||||
@ -66,9 +62,11 @@ impl gui::GUI for UI {
|
||||
(self, animation::EventLoopMode::InputOnly)
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _input: UserInput) {
|
||||
// TODO Weird to mut self just to set window_size on the canvas
|
||||
fn draw(&mut self, g: &mut GfxCtx, _input: UserInput, window_size: Size) {
|
||||
graphics::clear(WHITE, g.gfx);
|
||||
g.ctx = self.canvas.get_transformed_context(&g.orig_ctx);
|
||||
g.ctx = self.canvas
|
||||
.get_transformed_context(&g.orig_ctx, window_size);
|
||||
|
||||
let mut labels: Vec<(Pt2D, String)> = Vec::new();
|
||||
|
||||
|
@ -5,10 +5,10 @@ use piston::window::Size;
|
||||
use std;
|
||||
|
||||
pub trait GUI {
|
||||
fn event(self, input: &mut UserInput, window_size: &Size) -> (Self, animation::EventLoopMode)
|
||||
fn event(self, input: &mut UserInput) -> (Self, animation::EventLoopMode)
|
||||
where
|
||||
Self: std::marker::Sized;
|
||||
|
||||
// TODO just take OSD stuff, not all of the input
|
||||
fn draw(&self, g: &mut GfxCtx, input: UserInput);
|
||||
fn draw(&mut self, g: &mut GfxCtx, input: UserInput, window_size: Size);
|
||||
}
|
||||
|
@ -80,16 +80,22 @@ fn main() {
|
||||
texture_settings,
|
||||
).expect("Could not load font");
|
||||
|
||||
let size = &window.draw_size();
|
||||
let window_size = window.draw_size();
|
||||
if flags.experimental_gui {
|
||||
run(events, window, gl, glyphs, experimental::UI::new());
|
||||
run(
|
||||
events,
|
||||
window,
|
||||
gl,
|
||||
glyphs,
|
||||
experimental::UI::new(window_size),
|
||||
);
|
||||
} else {
|
||||
run(
|
||||
events,
|
||||
window,
|
||||
gl,
|
||||
glyphs,
|
||||
ui::UI::new(&flags.abst_input, size, flags.rng_seed),
|
||||
ui::UI::new(&flags.abst_input, window_size, flags.rng_seed),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -105,7 +111,7 @@ fn run<T: gui::GUI>(
|
||||
|
||||
while let Some(ev) = events.next(&mut window) {
|
||||
let mut input = UserInput::new(ev.clone());
|
||||
let (new_gui, new_event_mode) = gui.event(&mut input, &window.draw_size());
|
||||
let (new_gui, new_event_mode) = gui.event(&mut input);
|
||||
gui = new_gui;
|
||||
// Don't constantly reset the events struct -- only when laziness changes.
|
||||
if new_event_mode != last_event_mode {
|
||||
@ -121,9 +127,9 @@ fn run<T: gui::GUI>(
|
||||
gfx: g,
|
||||
orig_ctx: c,
|
||||
ctx: c,
|
||||
window_size: window.draw_size(),
|
||||
},
|
||||
input,
|
||||
window.draw_size(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ use ezgui::input::UserInput;
|
||||
use ezgui::menu;
|
||||
use graphics;
|
||||
use piston::input::{Key, MouseCursorEvent};
|
||||
use piston::window::Size;
|
||||
use std::str::FromStr;
|
||||
use std::string::ToString;
|
||||
use strum::IntoEnumIterator;
|
||||
@ -33,7 +32,7 @@ impl ColorPicker {
|
||||
pub fn handle_event(
|
||||
self,
|
||||
input: &mut UserInput,
|
||||
window_size: &Size,
|
||||
canvas: &Canvas,
|
||||
cs: &mut ColorScheme,
|
||||
) -> ColorPicker {
|
||||
match self {
|
||||
@ -78,7 +77,7 @@ impl ColorPicker {
|
||||
|
||||
if let Some(pos) = input.use_event_directly().mouse_cursor_args() {
|
||||
// TODO argh too much casting
|
||||
let (start_x, start_y) = get_screen_offset(window_size);
|
||||
let (start_x, start_y) = get_screen_offset(canvas);
|
||||
let x = (pos[0] - (start_x as f64)) / (TILE_DIMS as f64) / 255.0;
|
||||
let y = (pos[1] - (start_y as f64)) / (TILE_DIMS as f64) / 255.0;
|
||||
if x >= 0.0 && x <= 1.0 && y >= 0.0 && y <= 1.0 {
|
||||
@ -102,7 +101,7 @@ impl ColorPicker {
|
||||
canvas.draw_mouse_tooltip(g, &menu.lines_to_display());
|
||||
}
|
||||
ColorPicker::PickingColor(_, _) => {
|
||||
let (start_x, start_y) = get_screen_offset(&g.window_size);
|
||||
let (start_x, start_y) = get_screen_offset(canvas);
|
||||
|
||||
for x in 0..WIDTH {
|
||||
for y in 0..HEIGHT {
|
||||
@ -126,11 +125,11 @@ impl ColorPicker {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_screen_offset(window_size: &Size) -> (u32, u32) {
|
||||
fn get_screen_offset(canvas: &Canvas) -> (u32, u32) {
|
||||
let total_width = TILE_DIMS * WIDTH;
|
||||
let total_height = TILE_DIMS * HEIGHT;
|
||||
let start_x = (window_size.width - total_width) / 2;
|
||||
let start_y = (window_size.height - total_height) / 2;
|
||||
let start_x = (canvas.window_size.width - total_width) / 2;
|
||||
let start_y = (canvas.window_size.height - total_height) / 2;
|
||||
(start_x, start_y)
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ use geom::Pt2D;
|
||||
use graphics::math::Vec2d;
|
||||
use map_model::{geometry, BuildingID, IntersectionID, Map, ParcelID, RoadID};
|
||||
use piston::input::Key;
|
||||
use piston::window::Size;
|
||||
use render;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
|
||||
@ -86,13 +85,7 @@ impl Validator {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn event(
|
||||
&mut self,
|
||||
input: &mut UserInput,
|
||||
canvas: &mut Canvas,
|
||||
window_size: &Size,
|
||||
map: &Map,
|
||||
) -> bool {
|
||||
pub fn event(&mut self, input: &mut UserInput, canvas: &mut Canvas, map: &Map) -> bool {
|
||||
// Initialize or advance?
|
||||
if !self.current_problem.is_some()
|
||||
|| input.key_pressed(Key::N, "Press N to see the next problem")
|
||||
@ -102,7 +95,7 @@ impl Validator {
|
||||
if let Some((id1, id2)) = self.current_problem {
|
||||
println!("{:?} and {:?} intersect", id1, id2);
|
||||
let pt = get_pt(map, id1);
|
||||
canvas.center_on_map_pt(pt.x(), pt.y(), window_size);
|
||||
canvas.center_on_map_pt(pt.x(), pt.y());
|
||||
// TODO also modify selection state to highlight stuff?
|
||||
return false;
|
||||
} else {
|
||||
|
@ -3,7 +3,6 @@ use ezgui::input::UserInput;
|
||||
use ezgui::text_box::TextBox;
|
||||
use map_model::{geometry, BuildingID, IntersectionID, Map, ParcelID, RoadID};
|
||||
use piston::input::Key;
|
||||
use piston::window::Size;
|
||||
use plugins::selection::SelectionState;
|
||||
use std::usize;
|
||||
|
||||
@ -18,7 +17,6 @@ impl WarpState {
|
||||
input: &mut UserInput,
|
||||
map: &Map,
|
||||
canvas: &mut Canvas,
|
||||
window_size: &Size,
|
||||
selection_state: &mut SelectionState,
|
||||
) -> WarpState {
|
||||
match self {
|
||||
@ -35,7 +33,7 @@ impl WarpState {
|
||||
WarpState::EnteringSearch(mut tb) => {
|
||||
if tb.event(input.use_event_directly()) {
|
||||
input.consume_event();
|
||||
warp(tb.line, map, canvas, window_size, selection_state);
|
||||
warp(tb.line, map, canvas, selection_state);
|
||||
WarpState::Empty
|
||||
} else {
|
||||
input.consume_event();
|
||||
@ -54,13 +52,7 @@ impl WarpState {
|
||||
}
|
||||
}
|
||||
|
||||
fn warp(
|
||||
line: String,
|
||||
map: &Map,
|
||||
canvas: &mut Canvas,
|
||||
window_size: &Size,
|
||||
selection_state: &mut SelectionState,
|
||||
) {
|
||||
fn warp(line: String, map: &Map, canvas: &mut Canvas, selection_state: &mut SelectionState) {
|
||||
let pt = match usize::from_str_radix(&line[1..line.len()], 10) {
|
||||
Ok(idx) => match line.chars().next().unwrap() {
|
||||
'r' => {
|
||||
@ -92,5 +84,5 @@ fn warp(
|
||||
return;
|
||||
}
|
||||
};
|
||||
canvas.center_on_map_pt(pt.x(), pt.y(), window_size);
|
||||
canvas.center_on_map_pt(pt.x(), pt.y());
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ pub struct UI {
|
||||
}
|
||||
|
||||
impl UI {
|
||||
pub fn new(abst_path: &str, window_size: &Size, rng_seed: Option<u8>) -> UI {
|
||||
pub fn new(abst_path: &str, window_size: Size, rng_seed: Option<u8>) -> UI {
|
||||
println!("Opening {}", abst_path);
|
||||
let map = map_model::Map::new(abst_path).expect("Couldn't load map");
|
||||
let (draw_map, center_pt) = render::DrawMap::new(&map);
|
||||
@ -119,7 +119,7 @@ impl UI {
|
||||
color_picker: ColorPicker::new(),
|
||||
geom_validator: None,
|
||||
|
||||
canvas: Canvas::new(),
|
||||
canvas: Canvas::new(window_size),
|
||||
cs: ColorScheme::load("color_scheme").unwrap(),
|
||||
};
|
||||
|
||||
@ -134,8 +134,7 @@ impl UI {
|
||||
}
|
||||
Err(_) => {
|
||||
println!("Couldn't load editor_state, just centering initial view");
|
||||
ui.canvas
|
||||
.center_on_map_pt(center_pt.x(), center_pt.y(), window_size);
|
||||
ui.canvas.center_on_map_pt(center_pt.x(), center_pt.y());
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,10 +154,10 @@ impl UI {
|
||||
self.debug_mode.handle_zoom(old_zoom, new_zoom);
|
||||
}
|
||||
|
||||
fn mouseover_something(&self, window_size: &Size) -> Option<ID> {
|
||||
fn mouseover_something(&self) -> Option<ID> {
|
||||
let (x, y) = self.canvas.get_cursor_in_map_space();
|
||||
|
||||
let screen_bbox = self.canvas.get_screen_bbox(window_size);
|
||||
let screen_bbox = self.canvas.get_screen_bbox();
|
||||
|
||||
let roads_onscreen = if self.show_roads.is_enabled() {
|
||||
self.draw_map.get_roads_onscreen(screen_bbox, &self.hider)
|
||||
@ -329,11 +328,7 @@ impl UI {
|
||||
}
|
||||
|
||||
impl gui::GUI for UI {
|
||||
fn event(
|
||||
mut self,
|
||||
input: &mut UserInput,
|
||||
window_size: &Size,
|
||||
) -> (UI, animation::EventLoopMode) {
|
||||
fn event(mut self, input: &mut UserInput) -> (UI, animation::EventLoopMode) {
|
||||
let mut event_loop_mode = animation::EventLoopMode::InputOnly;
|
||||
let mut edit_mode = false;
|
||||
|
||||
@ -368,8 +363,9 @@ impl gui::GUI for UI {
|
||||
// TODO disabling temporarily since it conflicts with warp. need to solve the
|
||||
// one-plugin-at-a-time problem.
|
||||
if !edit_mode && false {
|
||||
self.color_picker = self.color_picker
|
||||
.handle_event(input, window_size, &mut self.cs);
|
||||
self.color_picker =
|
||||
self.color_picker
|
||||
.handle_event(input, &mut self.canvas, &mut self.cs);
|
||||
}
|
||||
|
||||
self.current_search_state = self.current_search_state.event(input);
|
||||
@ -377,7 +373,6 @@ impl gui::GUI for UI {
|
||||
input,
|
||||
&self.map,
|
||||
&mut self.canvas,
|
||||
window_size,
|
||||
&mut self.current_selection_state,
|
||||
);
|
||||
|
||||
@ -422,7 +417,7 @@ impl gui::GUI for UI {
|
||||
if !self.canvas.is_dragging() && input.use_event_directly().mouse_cursor_args().is_some()
|
||||
&& new_zoom >= MIN_ZOOM_FOR_MOUSEOVER
|
||||
{
|
||||
let item = self.mouseover_something(window_size);
|
||||
let item = self.mouseover_something();
|
||||
self.current_selection_state = self.current_selection_state.handle_mouseover(item);
|
||||
}
|
||||
self.hider.event(input, &mut self.current_selection_state);
|
||||
@ -479,7 +474,7 @@ impl gui::GUI for UI {
|
||||
}
|
||||
|
||||
if let Some(mut v) = self.geom_validator {
|
||||
if v.event(input, &mut self.canvas, window_size, &self.map) {
|
||||
if v.event(input, &mut self.canvas, &self.map) {
|
||||
self.geom_validator = None;
|
||||
} else {
|
||||
self.geom_validator = Some(v);
|
||||
@ -512,12 +507,14 @@ impl gui::GUI for UI {
|
||||
(self, event_loop_mode)
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, input: UserInput) {
|
||||
// TODO Weird to mut self just to set window_size on the canvas
|
||||
fn draw(&mut self, g: &mut GfxCtx, input: UserInput, window_size: Size) {
|
||||
graphics::clear(self.cs.get(Colors::Background), g.gfx);
|
||||
|
||||
g.ctx = self.canvas.get_transformed_context(&g.orig_ctx);
|
||||
g.ctx = self.canvas
|
||||
.get_transformed_context(&g.orig_ctx, window_size);
|
||||
|
||||
let screen_bbox = self.canvas.get_screen_bbox(&g.window_size);
|
||||
let screen_bbox = self.canvas.get_screen_bbox();
|
||||
|
||||
if self.show_parcels.is_enabled() {
|
||||
for p in &self.draw_map.get_parcels_onscreen(screen_bbox) {
|
||||
|
@ -20,10 +20,12 @@ pub struct Canvas {
|
||||
cursor_y: f64,
|
||||
|
||||
left_mouse_drag_from: Option<[f64; 2]>,
|
||||
|
||||
pub window_size: Size,
|
||||
}
|
||||
|
||||
impl Canvas {
|
||||
pub fn new() -> Canvas {
|
||||
pub fn new(window_size: Size) -> Canvas {
|
||||
Canvas {
|
||||
cam_x: 0.0,
|
||||
cam_y: 0.0,
|
||||
@ -33,6 +35,7 @@ impl Canvas {
|
||||
cursor_y: 0.0,
|
||||
|
||||
left_mouse_drag_from: None,
|
||||
window_size,
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +76,9 @@ impl Canvas {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_transformed_context(&self, ctx: &Context) -> Context {
|
||||
// TODO rename
|
||||
pub fn get_transformed_context(&mut self, ctx: &Context, window_size: Size) -> Context {
|
||||
self.window_size = window_size;
|
||||
ctx.trans(-self.cam_x, -self.cam_y).zoom(self.cam_zoom)
|
||||
}
|
||||
|
||||
@ -90,7 +95,7 @@ impl Canvas {
|
||||
return;
|
||||
}
|
||||
let (_, height) = text::dims(g, lines);
|
||||
let y1 = f64::from(g.window_size.height) - height;
|
||||
let y1 = f64::from(self.window_size.height) - height;
|
||||
text::draw_text_bubble(g, lines, 0.0, y1);
|
||||
}
|
||||
|
||||
@ -124,9 +129,9 @@ impl Canvas {
|
||||
(y + self.cam_y) / self.cam_zoom
|
||||
}
|
||||
|
||||
pub fn center_on_map_pt(&mut self, x: f64, y: f64, window_size: &Size) {
|
||||
self.cam_x = (x * self.cam_zoom) - (f64::from(window_size.width) / 2.0);
|
||||
self.cam_y = (y * self.cam_zoom) - (f64::from(window_size.height) / 2.0);
|
||||
pub fn center_on_map_pt(&mut self, x: f64, y: f64) {
|
||||
self.cam_x = (x * self.cam_zoom) - (f64::from(self.window_size.width) / 2.0);
|
||||
self.cam_y = (y * self.cam_zoom) - (f64::from(self.window_size.height) / 2.0);
|
||||
}
|
||||
|
||||
fn map_to_screen_x(&self, x: f64) -> f64 {
|
||||
@ -137,15 +142,15 @@ impl Canvas {
|
||||
}
|
||||
|
||||
// little weird to return an aabb_quadtree type here. need standard geometry types
|
||||
pub fn get_screen_bbox(&self, window_size: &Size) -> Rect {
|
||||
pub fn get_screen_bbox(&self) -> Rect {
|
||||
Rect {
|
||||
top_left: Point {
|
||||
x: self.screen_to_map_x(0.0) as f32,
|
||||
y: self.screen_to_map_y(0.0) as f32,
|
||||
},
|
||||
bottom_right: Point {
|
||||
x: self.screen_to_map_x(f64::from(window_size.width)) as f32,
|
||||
y: self.screen_to_map_y(f64::from(window_size.height)) as f32,
|
||||
x: self.screen_to_map_x(f64::from(self.window_size.width)) as f32,
|
||||
y: self.screen_to_map_y(f64::from(self.window_size.height)) as f32,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ use graphics::Context;
|
||||
use graphics::character::CharacterCache;
|
||||
use opengl_graphics::{GlGraphics, Texture};
|
||||
use piston::input::Key;
|
||||
use piston::window::Size;
|
||||
|
||||
//struct GfxCtx<'a, G: 'a + Graphics, C: 'a + CharacterCache<Texture = G::Texture>> {
|
||||
pub struct GfxCtx<'a> {
|
||||
@ -23,7 +22,6 @@ pub struct GfxCtx<'a> {
|
||||
pub orig_ctx: Context,
|
||||
pub ctx: Context,
|
||||
pub gfx: &'a mut GlGraphics,
|
||||
pub window_size: Size,
|
||||
}
|
||||
|
||||
pub struct ToggleableLayer {
|
||||
|
Loading…
Reference in New Issue
Block a user