try screenshot capture again. it's very slow and broken.

This commit is contained in:
Dustin Carlino 2019-01-13 14:47:11 -08:00
parent 66006618df
commit a94fddb209
5 changed files with 132 additions and 43 deletions

View File

@ -22,6 +22,8 @@ pub struct UI<S: UIState> {
state: S, state: S,
canvas: Canvas, canvas: Canvas,
cs: ColorScheme, cs: ColorScheme,
// TODO Shouldn't this be a proper plugin?
take_screenshot: bool,
} }
impl<S: UIState> GUI<RenderingHints> for UI<S> { impl<S: UIState> GUI<RenderingHints> for UI<S> {
@ -232,6 +234,11 @@ impl<S: UIState> GUI<RenderingHints> for UI<S> {
input.populate_osd(&mut hints.osd); input.populate_osd(&mut hints.osd);
self.take_screenshot = false;
if input.unimportant_key_pressed(Key::F1, "take screenshot") {
self.take_screenshot = true;
}
(hints.mode, hints) (hints.mode, hints)
} }
@ -240,6 +247,10 @@ impl<S: UIState> GUI<RenderingHints> for UI<S> {
} }
fn draw(&self, g: &mut GfxCtx, hints: &RenderingHints) { fn draw(&self, g: &mut GfxCtx, hints: &RenderingHints) {
if self.take_screenshot {
g.render_to_buffer(&self.canvas);
}
g.clear(self.cs.get_def("map background", Color::rgb(242, 239, 233))); g.clear(self.cs.get_def("map background", Color::rgb(242, 239, 233)));
let ctx = Ctx { let ctx = Ctx {
@ -270,6 +281,11 @@ impl<S: UIState> GUI<RenderingHints> for UI<S> {
// soon, so meh // soon, so meh
self.canvas self.canvas
.draw_blocking_text(g, hints.osd.clone(), BOTTOM_LEFT); .draw_blocking_text(g, hints.osd.clone(), BOTTOM_LEFT);
if self.take_screenshot {
g.save_buffer("screenshot.png");
info!("Captured screenshot.png");
}
} }
fn dump_before_abort(&self) { fn dump_before_abort(&self) {
@ -298,6 +314,7 @@ impl<S: UIState> UI<S> {
state, state,
canvas, canvas,
cs: ColorScheme::load().unwrap(), cs: ColorScheme::load().unwrap(),
take_screenshot: false,
}; };
match abstutil::read_json::<EditorState>("../editor_state") { match abstutil::read_json::<EditorState>("../editor_state") {

View File

@ -8,17 +8,14 @@ edition = "2018"
abstutil = { path = "../abstutil" } abstutil = { path = "../abstutil" }
dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] } dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] }
geom = { path = "../geom" } geom = { path = "../geom" }
graphics_buffer = "0.5.0"
log = "0.4.5" log = "0.4.5"
ordered-float = "1.0.1" ordered-float = "1.0.1"
palette = "0.4" palette = "0.4"
piston = "0.37.0" piston = "0.39.0"
piston2d-graphics = "0.26.0" piston2d-graphics = "0.28.0"
piston2d-opengl_graphics = "0.53.0" piston2d-opengl_graphics = "0.57.0"
# Newer versions start reading DPI, which is very broken on my system. pistoncore-glutin_window = "0.51.1"
# WINIT_HIDPI_FACTOR=1.0 as an environment variable fixes, but just pin to an
# older version for now... before
# https://github.com/tomaka/winit/commit/1b74822cfc0cb7fba4ed4940a3faae9499fcda95.
pistoncore-glutin_window = "0.47.0"
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
textwrap = "0.11" textwrap = "0.11"

View File

@ -152,6 +152,7 @@ pub enum Key {
RightArrow, RightArrow,
UpArrow, UpArrow,
DownArrow, DownArrow,
F1,
} }
impl Key { impl Key {
@ -210,7 +211,8 @@ impl Key {
| Key::LeftArrow | Key::LeftArrow
| Key::RightArrow | Key::RightArrow
| Key::UpArrow | Key::UpArrow
| Key::DownArrow => None, | Key::DownArrow
| Key::F1 => None,
} }
} }
@ -227,6 +229,7 @@ impl Key {
Key::RightArrow => "→ arrow".to_string(), Key::RightArrow => "→ arrow".to_string(),
Key::UpArrow => "".to_string(), Key::UpArrow => "".to_string(),
Key::DownArrow => "".to_string(), Key::DownArrow => "".to_string(),
Key::F1 => "F1".to_string(),
// These have to_char, but override here // These have to_char, but override here
Key::Space => "Space".to_string(), Key::Space => "Space".to_string(),
_ => self.to_char(false).unwrap().to_string(), _ => self.to_char(false).unwrap().to_string(),
@ -294,6 +297,7 @@ impl Key {
pi::Key::Right => Key::RightArrow, pi::Key::Right => Key::RightArrow,
pi::Key::Up => Key::UpArrow, pi::Key::Up => Key::UpArrow,
pi::Key::Down => Key::DownArrow, pi::Key::Down => Key::DownArrow,
pi::Key::F1 => Key::F1,
_ => { _ => {
println!("Unknown piston key {:?}", key); println!("Unknown piston key {:?}", key);
return None; return None;

View File

@ -28,6 +28,7 @@ pub use crate::top_menu::{Folder, TopMenu};
pub use crate::wizard::{Wizard, WrappedWizard}; pub use crate::wizard::{Wizard, WrappedWizard};
use geom::Pt2D; use geom::Pt2D;
use graphics::Transformed; use graphics::Transformed;
use graphics_buffer::{RenderBuffer, IDENTITY};
use opengl_graphics::GlGraphics; use opengl_graphics::GlGraphics;
use std::mem; use std::mem;
@ -38,7 +39,10 @@ pub const TOP_MENU_HEIGHT: f64 = text::LINE_HEIGHT;
pub struct GfxCtx<'a> { pub struct GfxCtx<'a> {
orig_ctx: graphics::Context, orig_ctx: graphics::Context,
ctx: graphics::Context, ctx: graphics::Context,
// TODO Either gfx or save_to_buffer, not both.
gfx: &'a mut GlGraphics, gfx: &'a mut GlGraphics,
// TODO The code duplication below sucks. Make the generics work.
save_to_buffer: Option<RenderBuffer>,
} }
impl<'a> GfxCtx<'a> { impl<'a> GfxCtx<'a> {
@ -47,9 +51,25 @@ impl<'a> GfxCtx<'a> {
gfx: g, gfx: g,
orig_ctx: c, orig_ctx: c,
ctx: c, ctx: c,
save_to_buffer: None,
} }
} }
pub fn render_to_buffer(&mut self, canvas: &Canvas) {
assert!(self.save_to_buffer.is_none());
self.save_to_buffer = Some(RenderBuffer::new(
canvas.window_height as u32,
canvas.window_height as u32,
));
self.orig_ctx.view = IDENTITY;
self.orig_ctx.transform = IDENTITY;
canvas.start_drawing(self);
}
pub fn save_buffer(&mut self, filename: &str) {
self.save_to_buffer.take().unwrap().save(filename).unwrap();
}
// Up to the caller to call unfork()! // Up to the caller to call unfork()!
// TODO Canvas doesn't understand this change, so things like text drawing that use // TODO Canvas doesn't understand this change, so things like text drawing that use
// map_to_screen will just be confusing. // map_to_screen will just be confusing.
@ -71,7 +91,11 @@ impl<'a> GfxCtx<'a> {
} }
pub fn clear(&mut self, color: Color) { pub fn clear(&mut self, color: Color) {
graphics::clear(color.0, self.gfx); if let Some(ref mut buf) = self.save_to_buffer {
graphics::clear(color.0, buf);
} else {
graphics::clear(color.0, self.gfx);
}
} }
// Use graphics::Line internally for now, but make it easy to switch to something else by // Use graphics::Line internally for now, but make it easy to switch to something else by
@ -88,18 +112,33 @@ impl<'a> GfxCtx<'a> {
pub fn draw_arrow(&mut self, color: Color, thickness: f64, line: &geom::Line) { pub fn draw_arrow(&mut self, color: Color, thickness: f64, line: &geom::Line) {
// TODO Raw method doesn't work yet in all cases... // TODO Raw method doesn't work yet in all cases...
graphics::Line::new_round(color.0, thickness).draw_arrow( if let Some(ref mut buf) = self.save_to_buffer {
[ graphics::Line::new_round(color.0, thickness).draw_arrow(
line.pt1().x(), [
line.pt1().y(), line.pt1().x(),
line.pt2().x(), line.pt1().y(),
line.pt2().y(), line.pt2().x(),
], line.pt2().y(),
2.0 * thickness, ],
&self.ctx.draw_state, 2.0 * thickness,
self.ctx.transform, &self.ctx.draw_state,
self.gfx, self.ctx.transform,
); buf,
);
} else {
graphics::Line::new_round(color.0, thickness).draw_arrow(
[
line.pt1().x(),
line.pt1().y(),
line.pt2().x(),
line.pt2().y(),
],
2.0 * thickness,
&self.ctx.draw_state,
self.ctx.transform,
self.gfx,
);
}
/*use dimensioned::si; /*use dimensioned::si;
let head_size = 2.0 * thickness; let head_size = 2.0 * thickness;
@ -135,12 +174,55 @@ impl<'a> GfxCtx<'a> {
} }
pub fn draw_polygon(&mut self, color: Color, poly: &geom::Polygon) { pub fn draw_polygon(&mut self, color: Color, poly: &geom::Polygon) {
for tri in &poly.triangles { if let Some(ref mut buf) = self.save_to_buffer {
graphics::Polygon::new(color.0).draw( for tri in &poly.triangles {
&[ graphics::Polygon::new(color.0).draw(
[tri.pt1.x(), tri.pt1.y()], &[
[tri.pt2.x(), tri.pt2.y()], [tri.pt1.x(), tri.pt1.y()],
[tri.pt3.x(), tri.pt3.y()], [tri.pt2.x(), tri.pt2.y()],
[tri.pt3.x(), tri.pt3.y()],
],
&self.ctx.draw_state,
self.ctx.transform,
buf,
);
}
} else {
for tri in &poly.triangles {
graphics::Polygon::new(color.0).draw(
&[
[tri.pt1.x(), tri.pt1.y()],
[tri.pt2.x(), tri.pt2.y()],
[tri.pt3.x(), tri.pt3.y()],
],
&self.ctx.draw_state,
self.ctx.transform,
self.gfx,
);
}
}
}
pub fn draw_circle(&mut self, color: Color, circle: &geom::Circle) {
if let Some(ref mut buf) = self.save_to_buffer {
graphics::Ellipse::new(color.0).draw(
[
circle.center.x() - circle.radius,
circle.center.y() - circle.radius,
2.0 * circle.radius,
2.0 * circle.radius,
],
&self.ctx.draw_state,
self.ctx.transform,
buf,
);
} else {
graphics::Ellipse::new(color.0).draw(
[
circle.center.x() - circle.radius,
circle.center.y() - circle.radius,
2.0 * circle.radius,
2.0 * circle.radius,
], ],
&self.ctx.draw_state, &self.ctx.draw_state,
self.ctx.transform, self.ctx.transform,
@ -148,20 +230,6 @@ impl<'a> GfxCtx<'a> {
); );
} }
} }
pub fn draw_circle(&mut self, color: Color, circle: &geom::Circle) {
graphics::Ellipse::new(color.0).draw(
[
circle.center.x() - circle.radius,
circle.center.y() - circle.radius,
2.0 * circle.radius,
2.0 * circle.radius,
],
&self.ctx.draw_state,
self.ctx.transform,
self.gfx,
);
}
} }
pub struct ToggleableLayer { pub struct ToggleableLayer {

View File

@ -4,7 +4,7 @@ use glutin_window::GlutinWindow;
use opengl_graphics::{GlGraphics, OpenGL}; use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventLoop, EventSettings, Events}; use piston::event_loop::{EventLoop, EventSettings, Events};
use piston::window::WindowSettings; use piston::window::WindowSettings;
use std::{panic, process}; use std::{env, panic, process};
pub trait GUI<T> { pub trait GUI<T> {
// Called once // Called once
@ -30,6 +30,9 @@ pub enum EventLoopMode {
} }
pub fn run<T, G: GUI<T>>(mut gui: G, window_title: &str) { pub fn run<T, G: GUI<T>>(mut gui: G, window_title: &str) {
// DPI is broken on my system; force the old behavior.
env::set_var("WINIT_HIDPI_FACTOR", "1.0");
let opengl = OpenGL::V3_2; let opengl = OpenGL::V3_2;
let settings = WindowSettings::new( let settings = WindowSettings::new(
window_title, window_title,