proper logging from the editor layer

This commit is contained in:
Dustin Carlino 2018-09-21 14:16:38 -07:00
parent f9e0b6facc
commit 6c7d4185b3
9 changed files with 83 additions and 55 deletions

View File

@ -97,3 +97,9 @@ nice UI features:
- filter by area
- remember where the log scroller is, even when hidden
- jump to end or beginning quickly
- start at the end
log crate is annoying -- cant initialize it, but also have something else hold
onto it. probably have to use lazy static. not even sure I'll use this implicit
style long-term -- when two sims are running side-by-side, might be very
necessary to plumb more log context anyway.

View File

@ -13,6 +13,8 @@ flame = "0.2.2"
generator = "0.6"
geo = "0.9.1"
geom = { path = "../geom" }
lazy_static = "1.1.0"
log = "0.4.5"
map_model = { path = "../map_model" }
piston = "*"
piston2d-graphics = "*"

View File

@ -11,6 +11,10 @@ extern crate generator;
extern crate geo;
extern crate geom;
extern crate graphics;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate map_model;
extern crate piston;
extern crate quick_xml;

View File

@ -1,55 +1,71 @@
use ezgui::{Canvas, GfxCtx, LogScroller, UserInput};
use log;
use log::{LevelFilter, Log, Metadata, Record};
use objects::ROOT_MENU;
use piston::input::Key;
use plugins::Colorizer;
use std::sync::Mutex;
// TODO This is all total boilerplate!
pub enum DisplayLogs {
Inactive,
Active(LogScroller),
lazy_static! {
static ref LOGGER: Mutex<LogScroller> = Mutex::new(LogScroller::new_with_capacity(100));
}
static LOG_ADAPTER: LogAdapter = LogAdapter;
pub struct DisplayLogs {
active: bool,
}
impl DisplayLogs {
pub fn new() -> DisplayLogs {
DisplayLogs::Inactive
log::set_max_level(LevelFilter::Debug);
log::set_logger(&LOG_ADAPTER).unwrap();
DisplayLogs { active: false }
}
pub fn event(&mut self, input: &mut UserInput) -> bool {
let mut new_state: Option<DisplayLogs> = None;
match self {
DisplayLogs::Inactive => {
if input.unimportant_key_pressed(
Key::Comma,
ROOT_MENU,
"show logs",
) {
let mut scroller = LogScroller::new_with_capacity(100);
for i in 0..150 {
scroller.add_line(&format!("Sup line {}", i));
}
new_state = Some(DisplayLogs::Active(scroller));
}
}
DisplayLogs::Active(ref mut scroller) => {
if scroller.event(input) {
new_state = Some(DisplayLogs::Inactive);
}
if !self.active {
if input.unimportant_key_pressed(Key::Comma, ROOT_MENU, "show logs") {
self.active = true;
return true;
} else {
return false;
}
}
if let Some(s) = new_state {
*self = s;
}
match self {
DisplayLogs::Inactive => false,
_ => true,
if LOGGER.lock().unwrap().event(input) {
self.active = false;
}
self.active
}
pub fn draw(&self, g: &mut GfxCtx, canvas: &Canvas) {
if let DisplayLogs::Active(scroller) = self {
scroller.draw(g, canvas);
if self.active {
LOGGER.lock().unwrap().draw(g, canvas);
}
}
}
impl Colorizer for DisplayLogs {}
struct LogAdapter;
impl Log for LogAdapter {
fn enabled(&self, _metadata: &Metadata) -> bool {
true
}
fn log(&self, record: &Record) {
let line = format!(
"[{}] [{}] {}",
record.level(),
record.target(),
record.args()
);
println!("{}", line);
// TODO could handle newlines here
LOGGER.lock().unwrap().add_line(&line);
}
fn flush(&self) {}
}

View File

@ -73,55 +73,55 @@ fn warp(line: String, map: &Map, sim: &Sim, canvas: &mut Canvas, selected: &mut
let id = RoadID(idx);
if let Some(r) = map.maybe_get_r(id) {
let l = map.get_l(r.children_forwards[0].0);
println!("Warping to {}, which belongs to {}", l.id, id);
info!(target: "UI", "Warping to {}, which belongs to {}", l.id, id);
*selected = Some(ID::Lane(l.id));
l.first_pt()
} else {
println!("{} doesn't exist", id);
warn!(target: "UI", "{} doesn't exist", id);
return;
}
}
'l' => {
let id = LaneID(idx);
if let Some(l) = map.maybe_get_l(id) {
println!("Warping to {}", id);
info!(target: "UI", "Warping to {}", id);
*selected = Some(ID::Lane(id));
l.first_pt()
} else {
println!("{} doesn't exist", id);
warn!(target: "UI", "{} doesn't exist", id);
return;
}
}
'i' => {
let id = IntersectionID(idx);
if let Some(i) = map.maybe_get_i(id) {
println!("Warping to {}", id);
info!(target: "UI", "Warping to {}", id);
*selected = Some(ID::Intersection(id));
i.point
} else {
println!("{} doesn't exist", id);
warn!(target: "UI", "{} doesn't exist", id);
return;
}
}
'b' => {
let id = BuildingID(idx);
if let Some(b) = map.maybe_get_b(id) {
println!("Warping to {}", id);
info!(target: "UI", "Warping to {}", id);
*selected = Some(ID::Building(id));
Pt2D::center(&b.points)
} else {
println!("{} doesn't exist", id);
warn!(target: "UI", "{} doesn't exist", id);
return;
}
}
'a' => {
let id = AreaID(idx);
if let Some(a) = map.maybe_get_a(id) {
println!("Warping to {}", id);
info!(target: "UI", "Warping to {}", id);
*selected = Some(ID::Area(id));
Pt2D::center(&a.points)
} else {
println!("{} doesn't exist", id);
warn!(target: "UI", "{} doesn't exist", id);
return;
}
}
@ -129,37 +129,37 @@ fn warp(line: String, map: &Map, sim: &Sim, canvas: &mut Canvas, selected: &mut
'e' => {
let id = ParcelID(idx);
if let Some(p) = map.maybe_get_p(id) {
println!("Warping to {}", id);
info!(target: "UI", "Warping to {}", id);
Pt2D::center(&p.points)
} else {
println!("{} doesn't exist", id);
warn!(target: "UI", "{} doesn't exist", id);
return;
}
}
'p' => {
let id = PedestrianID(idx);
if let Some(p) = sim.get_draw_ped(id, map) {
println!("Warping to {}", id);
info!(target: "UI", "Warping to {}", id);
*selected = Some(ID::Pedestrian(id));
p.pos
} else {
println!("{} doesn't exist", id);
warn!(target: "UI", "{} doesn't exist", id);
return;
}
}
'c' => {
let id = CarID(idx);
if let Some(c) = sim.get_draw_car(id, map) {
println!("Warping to {}", id);
info!(target: "UI", "Warping to {}", id);
*selected = Some(ID::Car(id));
c.front
} else {
println!("{} doesn't exist", id);
warn!(target: "UI", "{} doesn't exist", id);
return;
}
}
_ => {
println!("{} isn't a valid ID; Should be [libepc][0-9]+", line);
warn!(target: "UI", "{} isn't a valid ID; Should be [libepc][0-9]+", line);
return;
}
},

View File

@ -17,13 +17,13 @@ use piston::input::{Key, MouseCursorEvent};
use piston::window::Size;
use plugins::classification::OsmClassifier;
use plugins::color_picker::ColorPicker;
use plugins::logs::DisplayLogs;
use plugins::debug_objects::DebugObjectsState;
use plugins::draw_polygon::DrawPolygonState;
use plugins::floodfill::Floodfiller;
use plugins::follow::FollowState;
use plugins::geom_validation::Validator;
use plugins::hider::Hider;
use plugins::logs::DisplayLogs;
use plugins::road_editor::RoadEditor;
use plugins::search::SearchState;
use plugins::show_route::ShowRouteState;
@ -136,7 +136,7 @@ impl UIWrapper {
match abstutil::read_json::<EditorState>("editor_state") {
Ok(ref state) if *ui.map.get_name() == state.map_name => {
println!("Loaded previous editor_state");
info!(target: "UI", "Loaded previous editor_state");
ui.canvas.cam_x = state.cam_x;
ui.canvas.cam_y = state.cam_y;
ui.canvas.cam_zoom = state.cam_zoom;
@ -144,7 +144,7 @@ impl UIWrapper {
.load_savestate(&state.traffic_signals, &state.stop_signs);
}
_ => {
println!("Couldn't load editor_state or it's for a different map, so just centering initial view");
warn!(target: "UI", "Couldn't load editor_state or it's for a different map, so just centering initial view");
ui.canvas.center_on_map_pt(center_pt);
}
}

View File

@ -173,7 +173,7 @@ impl UserInput {
osd.add_line(a);
}
println!("{}", self.unimportant_actions_tree);
//println!("{}", self.unimportant_actions_tree);
}
fn reserve_key(&mut self, key: Key, action: &str) {

View File

@ -22,9 +22,9 @@ pub use canvas::Canvas;
use graphics::character::CharacterCache;
use graphics::types::Color;
pub use input::UserInput;
pub use log_scroller::LogScroller;
pub use menu::Menu;
use opengl_graphics::{GlGraphics, Texture};
pub use log_scroller::LogScroller;
use piston::input::Key;
pub use runner::{run, EventLoopMode, GUI};
pub use text::TextOSD;

View File

@ -84,7 +84,7 @@ impl LogScroller {
if !self.lines.is_empty() {
// TODO VecDeque can't be sliced, argh
let copy: Vec<&String> = self.lines.iter().collect();
for line in &copy[low_idx .. high_idx] {
for line in &copy[low_idx..high_idx] {
osd.add_line(line.to_string());
}
}