Optionally tile screenshots at smaller dimensions than the window. #440

This commit is contained in:
Dustin Carlino 2021-01-06 10:52:22 -08:00
parent 4cf133cc32
commit 92be9c57ed
6 changed files with 37 additions and 19 deletions

View File

@ -12,7 +12,7 @@ use map_model::{osm, ControlTrafficSignal, IntersectionID, NORMAL_LANE_THICKNESS
use sim::Sim;
use widgetry::{
lctrl, Btn, Cached, Checkbox, Choice, Color, DrawBaselayer, Drawable, EventCtx, GeomBatch,
GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, State, Text, UpdateType,
GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, ScreenDims, State, Text, UpdateType,
VerticalAlignment, Widget,
};
@ -59,7 +59,7 @@ impl DebugMode {
Checkbox::switch(ctx, "show route for all agents", Key::R, false),
Widget::col(vec![
Btn::text_fg("unhide everything").build_def(ctx, lctrl(Key::H)),
Btn::text_fg("screenshot everything").build_def(ctx, None),
Btn::text_fg("screenshot everything (for leaflet)").build_def(ctx, None),
Btn::text_fg("screenshot all of the everything").build_def(ctx, None),
Btn::text_fg("search OSM metadata").build_def(ctx, Key::Slash),
Btn::text_fg("clear OSM search results").build_def(ctx, lctrl(Key::Slash)),
@ -222,8 +222,8 @@ impl State<App> for DebugMode {
self.search_results = None;
self.reset_info(ctx);
}
"screenshot everything" => {
screenshot_everything(ctx, app);
"screenshot everything (for leaflet)" => {
screenshot_everything(ctx, app, ScreenDims::new(256.0, 256.0));
return Transition::Keep;
}
"screenshot all of the everything" => {
@ -784,7 +784,7 @@ impl State<App> for ScreenshotTest {
}
} else {
self.screenshot_done = true;
screenshot_everything(ctx, app);
screenshot_everything(ctx, app, ctx.canvas.get_window_dims());
// TODO Sometimes this still gets stuck and needs a mouse wiggle for input event?
Transition::Keep
}
@ -792,10 +792,11 @@ impl State<App> for ScreenshotTest {
fn draw(&self, _: &mut GfxCtx, _: &App) {}
}
fn screenshot_everything(ctx: &mut EventCtx, app: &App) {
fn screenshot_everything(ctx: &mut EventCtx, app: &App, dims: ScreenDims) {
let name = app.primary.map.get_name();
ctx.request_update(UpdateType::ScreenCaptureEverything {
dir: format!("screenshots/{}/{}", name.city, name.map),
zoom: 3.0,
dims,
});
}

View File

@ -363,9 +363,9 @@ impl PrerenderInnards {
self.window_adapter.draw_finished(gfc_ctx_innards)
}
pub(crate) fn screencap(&self, canvas: &Canvas, filename: String) -> anyhow::Result<()> {
let width = canvas.window_width as u32;
let height = canvas.window_height as u32;
pub(crate) fn screencap(&self, dims: ScreenDims, filename: String) -> anyhow::Result<()> {
let width = dims.width as u32;
let height = dims.height as u32;
let mut img = image::DynamicImage::new_rgba8(width, height);
let pixels = img.as_mut_rgba8().unwrap();

View File

@ -15,7 +15,11 @@ pub enum UpdateType {
InputOnly,
Game,
Pan,
ScreenCaptureEverything { dir: String, zoom: f64 },
ScreenCaptureEverything {
dir: String,
zoom: f64,
dims: ScreenDims,
},
}
pub struct EventCtx<'a> {

View File

@ -25,6 +25,8 @@
//#![warn(missing_docs)]
#[macro_use]
extern crate anyhow;
#[macro_use]
extern crate log;

View File

@ -124,7 +124,7 @@ impl<A: SharedAppState> State<A> {
}
}
// Returns naming hint. Logically consumes the number of uploads.
/// Returns naming hint. Logically consumes the number of uploads.
pub(crate) fn draw(&mut self, prerender: &Prerender, screenshot: bool) -> Option<String> {
let mut g = GfxCtx::new(prerender, &self.canvas, &self.style, screenshot);
@ -358,8 +358,10 @@ pub fn run<
running = true;
}
UpdateType::Pan => {}
UpdateType::ScreenCaptureEverything { dir, zoom } => {
if let Err(err) = screenshot_everything(&mut state, &dir, &prerender, zoom) {
UpdateType::ScreenCaptureEverything { dir, zoom, dims } => {
if let Err(err) =
screenshot_everything(&mut state, &dir, &prerender, zoom, dims)
{
error!("Couldn't screenshot everything: {}", err);
}
}

View File

@ -1,7 +1,7 @@
use abstutil::Timer;
use crate::runner::State;
use crate::{Prerender, SharedAppState};
use crate::{Prerender, ScreenDims, SharedAppState};
/// Take a screenshot of the entire canvas, tiling it based on the window's width and height.
pub(crate) fn screenshot_everything<A: SharedAppState>(
@ -9,10 +9,19 @@ pub(crate) fn screenshot_everything<A: SharedAppState>(
dir_path: &str,
prerender: &Prerender,
zoom: f64,
dims: ScreenDims,
) -> anyhow::Result<()> {
if dims.width > state.canvas.window_width || dims.height > state.canvas.window_height {
bail!(
"Can't take screenshots of dims {:?} when the window is only {:?}",
dims,
state.canvas.get_window_dims()
);
}
let mut timer = Timer::new("capturing screen");
let num_tiles_x = (state.canvas.map_dims.0 * zoom / state.canvas.window_width).ceil() as usize;
let num_tiles_y = (state.canvas.map_dims.1 * zoom / state.canvas.window_height).ceil() as usize;
let num_tiles_x = (state.canvas.map_dims.0 * zoom / dims.width).ceil() as usize;
let num_tiles_y = (state.canvas.map_dims.1 * zoom / dims.height).ceil() as usize;
let orig_zoom = state.canvas.cam_zoom;
let orig_x = state.canvas.cam_x;
let orig_y = state.canvas.cam_y;
@ -26,8 +35,8 @@ pub(crate) fn screenshot_everything<A: SharedAppState>(
for tile_y in 0..num_tiles_y {
for tile_x in 0..num_tiles_x {
timer.next();
state.canvas.cam_x = (tile_x as f64) * state.canvas.window_width;
state.canvas.cam_y = (tile_y as f64) * state.canvas.window_height;
state.canvas.cam_x = (tile_x as f64) * dims.width;
state.canvas.cam_y = (tile_y as f64) * dims.height;
let suffix = state.draw(prerender, true).unwrap_or_else(String::new);
let filename = format!(
@ -37,7 +46,7 @@ pub(crate) fn screenshot_everything<A: SharedAppState>(
tile_y + 1,
suffix
);
prerender.inner.screencap(&state.canvas, filename)?;
prerender.inner.screencap(dims, filename)?;
}
}