mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 16:36:02 +03:00
lift panic handling from UI's event to ezgui runner, use also for draw
This commit is contained in:
parent
e29ff690f8
commit
d61255a4b3
145
editor/src/ui.rs
145
editor/src/ui.rs
@ -19,7 +19,6 @@ use sim::{GetDrawAgents, Sim, SimFlags, Tick};
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::panic;
|
||||
use std::process;
|
||||
|
||||
const MIN_ZOOM_FOR_MOUSEOVER: f64 = 4.0;
|
||||
@ -42,21 +41,67 @@ pub struct UI {
|
||||
}
|
||||
|
||||
impl GUI<RenderingHints> for UI {
|
||||
fn event(&mut self, input: UserInput) -> (EventLoopMode, RenderingHints) {
|
||||
match panic::catch_unwind(panic::AssertUnwindSafe(|| self.inner_event(input))) {
|
||||
Ok(hints) => (hints.mode, hints),
|
||||
Err(err) => {
|
||||
error!("********************************************************************************");
|
||||
error!("UI broke! Primary sim:");
|
||||
self.primary.sim.dump_before_abort();
|
||||
if let Some((s, _)) = &self.secondary {
|
||||
error!("Secondary sim:");
|
||||
s.sim.dump_before_abort();
|
||||
fn event(&mut self, mut input: UserInput) -> (EventLoopMode, RenderingHints) {
|
||||
let mut hints = RenderingHints {
|
||||
mode: EventLoopMode::InputOnly,
|
||||
osd: Text::new(),
|
||||
suppress_intersection_icon: None,
|
||||
color_crosswalks: HashMap::new(),
|
||||
hide_crosswalks: HashSet::new(),
|
||||
hide_turn_icons: HashSet::new(),
|
||||
};
|
||||
|
||||
// First update the camera and handle zoom
|
||||
let old_zoom = self.canvas.cam_zoom;
|
||||
self.canvas.handle_event(&mut input);
|
||||
let new_zoom = self.canvas.cam_zoom;
|
||||
self.primary_plugins
|
||||
.layers_mut()
|
||||
.handle_zoom(old_zoom, new_zoom);
|
||||
|
||||
// Always handle mouseover
|
||||
if old_zoom >= MIN_ZOOM_FOR_MOUSEOVER && new_zoom < MIN_ZOOM_FOR_MOUSEOVER {
|
||||
self.primary.current_selection = None;
|
||||
}
|
||||
if !self.canvas.is_dragging()
|
||||
&& input.get_moved_mouse().is_some()
|
||||
&& new_zoom >= MIN_ZOOM_FOR_MOUSEOVER
|
||||
{
|
||||
self.primary.current_selection = self.mouseover_something();
|
||||
}
|
||||
|
||||
// If there's an active plugin, just run it.
|
||||
if let Some(idx) = self.active_plugin {
|
||||
if !self.run_plugin(idx, &mut input, &mut hints) {
|
||||
self.active_plugin = None;
|
||||
}
|
||||
} else {
|
||||
// Run each plugin, short-circuiting if the plugin claimed it was active.
|
||||
for idx in 0..self.plugins.list.len() + self.primary_plugins.list.len() {
|
||||
if self.run_plugin(idx, &mut input, &mut hints) {
|
||||
self.active_plugin = Some(idx);
|
||||
break;
|
||||
}
|
||||
self.save_editor_state();
|
||||
panic::resume_unwind(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Can do this at any time.
|
||||
if input.unimportant_key_pressed(Key::Escape, ROOT_MENU, "quit") {
|
||||
self.save_editor_state();
|
||||
self.cs.borrow().save();
|
||||
info!("Saved color_scheme");
|
||||
//cpuprofiler::PROFILER.lock().unwrap().stop().unwrap();
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
if self.primary.recalculate_current_selection {
|
||||
self.primary.recalculate_current_selection = false;
|
||||
self.primary.current_selection = self.mouseover_something();
|
||||
}
|
||||
|
||||
input.populate_osd(&mut hints.osd);
|
||||
|
||||
(hints.mode, hints)
|
||||
}
|
||||
|
||||
fn get_mut_canvas(&mut self) -> &mut Canvas {
|
||||
@ -109,6 +154,17 @@ impl GUI<RenderingHints> for UI {
|
||||
|
||||
self.canvas.draw_text(g, hints.osd, BOTTOM_LEFT);
|
||||
}
|
||||
|
||||
fn dump_before_abort(&self) {
|
||||
error!("********************************************************************************");
|
||||
error!("UI broke! Primary sim:");
|
||||
self.primary.sim.dump_before_abort();
|
||||
if let Some((s, _)) = &self.secondary {
|
||||
error!("Secondary sim:");
|
||||
s.sim.dump_before_abort();
|
||||
}
|
||||
self.save_editor_state();
|
||||
}
|
||||
}
|
||||
|
||||
// All of the state that's bound to a specific map+edit has to live here.
|
||||
@ -281,69 +337,6 @@ impl UI {
|
||||
ui
|
||||
}
|
||||
|
||||
fn inner_event(&mut self, mut input: UserInput) -> RenderingHints {
|
||||
let mut hints = RenderingHints {
|
||||
mode: EventLoopMode::InputOnly,
|
||||
osd: Text::new(),
|
||||
suppress_intersection_icon: None,
|
||||
color_crosswalks: HashMap::new(),
|
||||
hide_crosswalks: HashSet::new(),
|
||||
hide_turn_icons: HashSet::new(),
|
||||
};
|
||||
|
||||
// First update the camera and handle zoom
|
||||
let old_zoom = self.canvas.cam_zoom;
|
||||
self.canvas.handle_event(&mut input);
|
||||
let new_zoom = self.canvas.cam_zoom;
|
||||
self.primary_plugins
|
||||
.layers_mut()
|
||||
.handle_zoom(old_zoom, new_zoom);
|
||||
|
||||
// Always handle mouseover
|
||||
if old_zoom >= MIN_ZOOM_FOR_MOUSEOVER && new_zoom < MIN_ZOOM_FOR_MOUSEOVER {
|
||||
self.primary.current_selection = None;
|
||||
}
|
||||
if !self.canvas.is_dragging()
|
||||
&& input.get_moved_mouse().is_some()
|
||||
&& new_zoom >= MIN_ZOOM_FOR_MOUSEOVER
|
||||
{
|
||||
self.primary.current_selection = self.mouseover_something();
|
||||
}
|
||||
|
||||
// If there's an active plugin, just run it.
|
||||
if let Some(idx) = self.active_plugin {
|
||||
if !self.run_plugin(idx, &mut input, &mut hints) {
|
||||
self.active_plugin = None;
|
||||
}
|
||||
} else {
|
||||
// Run each plugin, short-circuiting if the plugin claimed it was active.
|
||||
for idx in 0..self.plugins.list.len() + self.primary_plugins.list.len() {
|
||||
if self.run_plugin(idx, &mut input, &mut hints) {
|
||||
self.active_plugin = Some(idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can do this at any time.
|
||||
if input.unimportant_key_pressed(Key::Escape, ROOT_MENU, "quit") {
|
||||
self.save_editor_state();
|
||||
self.cs.borrow().save();
|
||||
info!("Saved color_scheme");
|
||||
//cpuprofiler::PROFILER.lock().unwrap().stop().unwrap();
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
if self.primary.recalculate_current_selection {
|
||||
self.primary.recalculate_current_selection = false;
|
||||
self.primary.current_selection = self.mouseover_something();
|
||||
}
|
||||
|
||||
input.populate_osd(&mut hints.osd);
|
||||
|
||||
hints
|
||||
}
|
||||
|
||||
fn mouseover_something(&self) -> Option<ID> {
|
||||
let pt = self.canvas.get_cursor_in_map_space();
|
||||
|
||||
|
@ -4,11 +4,14 @@ use opengl_graphics::{Filter, GlGraphics, GlyphCache, OpenGL, TextureSettings};
|
||||
use piston::event_loop::{EventLoop, EventSettings, Events};
|
||||
use piston::input::RenderEvent;
|
||||
use piston::window::{Window, WindowSettings};
|
||||
use std::panic;
|
||||
|
||||
pub trait GUI<T> {
|
||||
fn event(&mut self, input: UserInput) -> (EventLoopMode, T);
|
||||
fn get_mut_canvas(&mut self) -> &mut Canvas;
|
||||
fn draw(&self, g: &mut GfxCtx, data: T);
|
||||
// Will be called if event or draw panics.
|
||||
fn dump_before_abort(&self) {}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
@ -40,7 +43,16 @@ pub fn run<T, G: GUI<T>>(mut gui: G, window_title: &str, initial_width: u32, ini
|
||||
|
||||
let mut last_event_mode = EventLoopMode::InputOnly;
|
||||
while let Some(ev) = events.next(&mut window) {
|
||||
let (new_event_mode, data) = gui.event(UserInput::new(ev.clone()));
|
||||
let (new_event_mode, data) = match panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
gui.event(UserInput::new(ev.clone()))
|
||||
})) {
|
||||
Ok(pair) => pair,
|
||||
Err(err) => {
|
||||
gui.dump_before_abort();
|
||||
panic::resume_unwind(err);
|
||||
}
|
||||
};
|
||||
|
||||
// Don't constantly reset the events struct -- only when laziness changes.
|
||||
if new_event_mode != last_event_mode {
|
||||
events.set_lazy(new_event_mode == EventLoopMode::InputOnly);
|
||||
@ -52,7 +64,12 @@ pub fn run<T, G: GUI<T>>(mut gui: G, window_title: &str, initial_width: u32, ini
|
||||
let mut g = GfxCtx::new(&mut glyphs, g, c);
|
||||
gui.get_mut_canvas()
|
||||
.start_drawing(&mut g, window.draw_size());
|
||||
gui.draw(&mut g, data);
|
||||
if let Err(err) =
|
||||
panic::catch_unwind(panic::AssertUnwindSafe(|| gui.draw(&mut g, data)))
|
||||
{
|
||||
gui.dump_before_abort();
|
||||
panic::resume_unwind(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user