mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 15:33:44 +03:00
after clicking a button, figure out if we're hovering over any new buttons that're created. kind of an invasive refactor to get to this, but worth it.
This commit is contained in:
parent
eb9050777b
commit
0ad371525b
@ -71,7 +71,7 @@ impl Canvas {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_event(&mut self, input: &mut UserInput) {
|
||||
pub(crate) fn handle_event(&mut self, input: &mut UserInput) {
|
||||
// Can't start dragging or zooming on top of covered area
|
||||
if self.get_cursor_in_map_space().is_some() {
|
||||
if input.left_mouse_button_pressed() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::assets::Assets;
|
||||
use crate::{
|
||||
Canvas, Color, GfxCtx, HorizontalAlignment, Line, Prerender, ScreenDims, Text, UserInput,
|
||||
VerticalAlignment,
|
||||
Canvas, Color, Event, GfxCtx, HorizontalAlignment, Line, Prerender, ScreenDims, Text,
|
||||
UserInput, VerticalAlignment,
|
||||
};
|
||||
use abstutil::{elapsed_seconds, Timer, TimerSink};
|
||||
use geom::Angle;
|
||||
@ -11,7 +11,8 @@ use std::collections::VecDeque;
|
||||
use std::time::Instant;
|
||||
|
||||
pub struct EventCtx<'a> {
|
||||
pub input: &'a mut UserInput,
|
||||
pub(crate) fake_mouseover: bool,
|
||||
pub input: UserInput,
|
||||
// TODO These two probably shouldn't be public
|
||||
pub canvas: &'a mut Canvas,
|
||||
pub prerender: &'a Prerender<'a>,
|
||||
@ -41,8 +42,25 @@ impl<'a> EventCtx<'a> {
|
||||
f(self, &mut timer)
|
||||
}
|
||||
|
||||
pub fn canvas_movement(&mut self) {
|
||||
self.canvas.handle_event(&mut self.input)
|
||||
}
|
||||
|
||||
pub(crate) fn fake_mouseover<F: FnMut(&mut EventCtx)>(&mut self, mut cb: F) {
|
||||
let mut tmp = EventCtx {
|
||||
fake_mouseover: true,
|
||||
input: UserInput::new(Event::NoOp, self.canvas),
|
||||
canvas: self.canvas,
|
||||
prerender: self.prerender,
|
||||
program: self.program,
|
||||
assets: self.assets,
|
||||
};
|
||||
cb(&mut tmp);
|
||||
}
|
||||
|
||||
pub fn redo_mouseover(&self) -> bool {
|
||||
self.input.window_lost_cursor()
|
||||
self.fake_mouseover
|
||||
|| self.input.window_lost_cursor()
|
||||
|| (!self.is_dragging() && self.input.get_moved_mouse().is_some())
|
||||
|| self.input.get_mouse_scroll().is_some()
|
||||
}
|
||||
|
@ -498,14 +498,19 @@ impl Composite {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn minimal_size(ctx: &EventCtx, top_level: ManagedWidget, top_left: ScreenPt) -> Composite {
|
||||
pub fn minimal_size(
|
||||
ctx: &mut EventCtx,
|
||||
top_level: ManagedWidget,
|
||||
top_left: ScreenPt,
|
||||
) -> Composite {
|
||||
let mut c = Composite::new(top_level, CompositePosition::MinimalTopLeft(top_left));
|
||||
c.recompute_layout(ctx);
|
||||
ctx.fake_mouseover(|ctx| assert!(c.event(ctx).is_none()));
|
||||
c
|
||||
}
|
||||
|
||||
pub fn minimal_size_with_fillers(
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
top_level: ManagedWidget,
|
||||
top_left: ScreenPt,
|
||||
fillers: Vec<(&str, Filler)>,
|
||||
@ -515,27 +520,30 @@ impl Composite {
|
||||
c.fillers.insert(name.to_string(), filler);
|
||||
}
|
||||
c.recompute_layout(ctx);
|
||||
ctx.fake_mouseover(|ctx| assert!(c.event(ctx).is_none()));
|
||||
c
|
||||
}
|
||||
|
||||
pub fn fill_screen(ctx: &EventCtx, top_level: ManagedWidget) -> Composite {
|
||||
pub fn fill_screen(ctx: &mut EventCtx, top_level: ManagedWidget) -> Composite {
|
||||
let mut c = Composite::new(top_level, CompositePosition::FillScreen);
|
||||
c.recompute_layout(ctx);
|
||||
ctx.fake_mouseover(|ctx| assert!(c.event(ctx).is_none()));
|
||||
c
|
||||
}
|
||||
|
||||
pub fn aligned(
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
(horiz, vert): (HorizontalAlignment, VerticalAlignment),
|
||||
top_level: ManagedWidget,
|
||||
) -> Composite {
|
||||
let mut c = Composite::new(top_level, CompositePosition::Aligned(horiz, vert));
|
||||
c.recompute_layout(ctx);
|
||||
ctx.fake_mouseover(|ctx| assert!(c.event(ctx).is_none()));
|
||||
c
|
||||
}
|
||||
|
||||
pub fn aligned_with_sliders(
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
(horiz, vert): (HorizontalAlignment, VerticalAlignment),
|
||||
top_level: ManagedWidget,
|
||||
sliders: Vec<(&str, Slider)>,
|
||||
@ -545,11 +553,12 @@ impl Composite {
|
||||
c.sliders.insert(name.to_string(), slider);
|
||||
}
|
||||
c.recompute_layout(ctx);
|
||||
ctx.fake_mouseover(|ctx| assert!(c.event(ctx).is_none()));
|
||||
c
|
||||
}
|
||||
|
||||
pub fn scrollable(
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
top_level: ManagedWidget,
|
||||
menus: Vec<(&str, Menu)>,
|
||||
) -> Composite {
|
||||
@ -572,6 +581,7 @@ impl Composite {
|
||||
c.top_level = ManagedWidget::row(vec![c.top_level, ManagedWidget::slider("scrollbar")]);
|
||||
c.recompute_layout(ctx);
|
||||
}
|
||||
ctx.fake_mouseover(|ctx| assert!(c.event(ctx).is_none()));
|
||||
c
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ impl<G: GUI> State<G> {
|
||||
) -> (State<G>, EventLoopMode, bool) {
|
||||
// It's impossible / very unlikey we'll grab the cursor in map space before the very first
|
||||
// start_drawing call.
|
||||
let mut input = UserInput::new(ev, &self.canvas);
|
||||
let input = UserInput::new(ev, &self.canvas);
|
||||
let mut gui = self.gui;
|
||||
let mut canvas = self.canvas;
|
||||
|
||||
@ -80,31 +80,32 @@ impl<G: GUI> State<G> {
|
||||
}
|
||||
|
||||
let assets = self.assets;
|
||||
let event_mode = match panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
gui.event(&mut EventCtx {
|
||||
input: &mut input,
|
||||
canvas: &mut canvas,
|
||||
assets: &assets,
|
||||
prerender,
|
||||
program,
|
||||
})
|
||||
})) {
|
||||
let mut ctx = EventCtx {
|
||||
fake_mouseover: false,
|
||||
input: input,
|
||||
canvas: &mut canvas,
|
||||
assets: &assets,
|
||||
prerender,
|
||||
program,
|
||||
};
|
||||
let event_mode = match panic::catch_unwind(panic::AssertUnwindSafe(|| gui.event(&mut ctx)))
|
||||
{
|
||||
Ok(pair) => pair,
|
||||
Err(err) => {
|
||||
gui.dump_before_abort(&canvas);
|
||||
panic::resume_unwind(err);
|
||||
}
|
||||
};
|
||||
self.gui = gui;
|
||||
self.canvas = canvas;
|
||||
self.assets = assets;
|
||||
// TODO We should always do has_been_consumed, but various hacks prevent this from being
|
||||
// true. For now, just avoid the specific annoying redraw case when a KeyRelease or Update
|
||||
// event is unused.
|
||||
let input_used = match ev {
|
||||
Event::KeyRelease(_) | Event::Update => input.has_been_consumed(),
|
||||
Event::KeyRelease(_) | Event::Update => ctx.input.has_been_consumed(),
|
||||
_ => true,
|
||||
};
|
||||
self.gui = gui;
|
||||
self.canvas = canvas;
|
||||
self.assets = assets;
|
||||
|
||||
(self, event_mode, input_used)
|
||||
}
|
||||
@ -296,7 +297,8 @@ pub fn run<G: GUI, F: FnOnce(&mut EventCtx) -> G>(settings: Settings, make_gui:
|
||||
};
|
||||
|
||||
let gui = make_gui(&mut EventCtx {
|
||||
input: &mut UserInput::new(Event::NoOp, &canvas),
|
||||
fake_mouseover: true,
|
||||
input: UserInput::new(Event::NoOp, &canvas),
|
||||
canvas: &mut canvas,
|
||||
assets: &assets,
|
||||
prerender: &prerender,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
text, Event, GfxCtx, HorizontalAlignment, InputResult, Key, Line, Text, UserInput,
|
||||
text, Event, EventCtx, GfxCtx, HorizontalAlignment, InputResult, Key, Line, Text,
|
||||
VerticalAlignment,
|
||||
};
|
||||
use simsearch::SimSearch;
|
||||
@ -85,8 +85,8 @@ impl<T: Clone + Hash + Eq> Autocomplete<T> {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn event(&mut self, input: &mut UserInput) -> InputResult<HashSet<T>> {
|
||||
let maybe_ev = input.use_event_directly();
|
||||
pub fn event(&mut self, ctx: &mut EventCtx) -> InputResult<HashSet<T>> {
|
||||
let maybe_ev = ctx.input.use_event_directly();
|
||||
if maybe_ev.is_none() {
|
||||
return InputResult::StillActive;
|
||||
}
|
||||
|
@ -440,7 +440,6 @@ impl SliderWithTextBox {
|
||||
}
|
||||
|
||||
pub fn event(&mut self, ctx: &mut EventCtx) -> InputResult<Time> {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
stack_vertically(
|
||||
ContainerOrientation::Centered,
|
||||
ctx,
|
||||
@ -453,7 +452,7 @@ impl SliderWithTextBox {
|
||||
InputResult::StillActive
|
||||
} else {
|
||||
let line_before = self.tb.get_line().to_string();
|
||||
match self.tb.event(ctx.input) {
|
||||
match self.tb.event(&mut ctx.input) {
|
||||
InputResult::Done(line, _) => {
|
||||
if let Ok(t) = Time::parse(&line) {
|
||||
if t >= self.low && t <= self.high {
|
||||
|
@ -98,7 +98,7 @@ impl Wizard {
|
||||
vec![self.tb.as_mut().unwrap()],
|
||||
);
|
||||
|
||||
match self.tb.as_mut().unwrap().event(ctx.input) {
|
||||
match self.tb.as_mut().unwrap().event(&mut ctx.input) {
|
||||
InputResult::StillActive => None,
|
||||
InputResult::Canceled => {
|
||||
self.alive = false;
|
||||
@ -256,7 +256,7 @@ impl<'a, 'b> WrappedWizard<'a, 'b> {
|
||||
.log_scroller
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.event(self.ctx.input)
|
||||
.event(&mut self.ctx.input)
|
||||
{
|
||||
self.wizard.log_scroller = None;
|
||||
self.wizard.alive = false;
|
||||
@ -370,7 +370,7 @@ impl<'a, 'b> WrappedWizard<'a, 'b> {
|
||||
.log_scroller
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.event(self.ctx.input)
|
||||
.event(&mut self.ctx.input)
|
||||
{
|
||||
self.wizard.confirmed_state.push(Box::new(()));
|
||||
self.wizard.log_scroller = None;
|
||||
|
@ -90,7 +90,7 @@ impl State for ABTestMode {
|
||||
}
|
||||
self.menu.event(ctx);
|
||||
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ struct ABTestSetup {
|
||||
impl State for ABTestSetup {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
self.menu.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if self.menu.action("quit") {
|
||||
return Transition::Pop;
|
||||
|
@ -114,7 +114,7 @@ pub fn all_challenges() -> BTreeMap<String, Vec<Challenge>> {
|
||||
tree
|
||||
}
|
||||
|
||||
pub fn challenges_picker(ctx: &EventCtx) -> Box<dyn State> {
|
||||
pub fn challenges_picker(ctx: &mut EventCtx) -> Box<dyn State> {
|
||||
let mut col = Vec::new();
|
||||
|
||||
col.push(ManagedWidget::row(vec![
|
||||
|
@ -93,7 +93,7 @@ impl ColorerBuilder {
|
||||
self.buildings.insert(b, color);
|
||||
}
|
||||
|
||||
pub fn build(self, ctx: &EventCtx, ui: &UI) -> Colorer {
|
||||
pub fn build(self, ctx: &mut EventCtx, ui: &UI) -> Colorer {
|
||||
let mut zoomed = GeomBatch::new();
|
||||
let mut unzoomed = GeomBatch::new();
|
||||
|
||||
@ -130,7 +130,7 @@ pub struct ColorLegend {
|
||||
}
|
||||
|
||||
impl ColorLegend {
|
||||
pub fn new(ctx: &EventCtx, header: Text, rows: Vec<(&str, Color)>) -> ColorLegend {
|
||||
pub fn new(ctx: &mut EventCtx, header: Text, rows: Vec<(&str, Color)>) -> ColorLegend {
|
||||
let mut col = vec![ManagedWidget::row(vec![
|
||||
ManagedWidget::draw_text(ctx, header),
|
||||
crate::managed::Composite::text_button(ctx, "X", None),
|
||||
|
@ -17,7 +17,7 @@ pub struct InfoPanel {
|
||||
}
|
||||
|
||||
impl InfoPanel {
|
||||
pub fn new(id: ID, ui: &mut UI, ctx: &EventCtx) -> InfoPanel {
|
||||
pub fn new(id: ID, ui: &mut UI, ctx: &mut EventCtx) -> InfoPanel {
|
||||
let mut col = vec![ManagedWidget::row(vec![
|
||||
{
|
||||
let mut txt = CommonState::default_osd(id.clone(), ui);
|
||||
|
@ -24,7 +24,7 @@ pub struct Minimap {
|
||||
}
|
||||
|
||||
impl Minimap {
|
||||
fn make_nav_panel(ctx: &EventCtx, zoom_lvl: usize) -> Composite {
|
||||
fn make_nav_panel(ctx: &mut EventCtx, zoom_lvl: usize) -> Composite {
|
||||
let square_len = 0.15 * ctx.canvas.window_width;
|
||||
let mut zoom_col = vec![ManagedWidget::btn(Button::rectangle_svg(
|
||||
"assets/speed/speed_up.svg",
|
||||
@ -118,7 +118,7 @@ impl Minimap {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(ctx: &EventCtx, ui: &UI) -> Minimap {
|
||||
pub fn new(ctx: &mut EventCtx, ui: &UI) -> Minimap {
|
||||
let zoom_lvl = 0;
|
||||
let mut m = Minimap {
|
||||
dragging: false,
|
||||
@ -304,7 +304,7 @@ pub struct VisibilityPanel {
|
||||
}
|
||||
|
||||
impl VisibilityPanel {
|
||||
fn make_panel(ctx: &EventCtx, acs: &AgentColorScheme) -> Composite {
|
||||
fn make_panel(ctx: &mut EventCtx, acs: &AgentColorScheme) -> Composite {
|
||||
let radius = 15.0;
|
||||
let mut col = vec![
|
||||
// TODO Too wide most of the time...
|
||||
@ -362,7 +362,7 @@ impl VisibilityPanel {
|
||||
)
|
||||
}
|
||||
|
||||
fn new(ctx: &EventCtx, ui: &UI) -> VisibilityPanel {
|
||||
fn new(ctx: &mut EventCtx, ui: &UI) -> VisibilityPanel {
|
||||
VisibilityPanel {
|
||||
acs: ui.agent_cs.clone(),
|
||||
composite: VisibilityPanel::make_panel(ctx, &ui.agent_cs),
|
||||
|
@ -30,7 +30,7 @@ impl Navigator {
|
||||
impl State for Navigator {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
let map = &ui.primary.map;
|
||||
match self.autocomplete.event(ctx.input) {
|
||||
match self.autocomplete.event(ctx) {
|
||||
InputResult::Canceled => Transition::Pop,
|
||||
InputResult::Done(name, ids) => {
|
||||
// Roads share intersections, so of course there'll be overlap here.
|
||||
@ -74,7 +74,7 @@ impl State for CrossStreet {
|
||||
// When None, this is done.
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
let map = &ui.primary.map;
|
||||
match self.autocomplete.event(ctx.input) {
|
||||
match self.autocomplete.event(ctx) {
|
||||
InputResult::Canceled => {
|
||||
// Just warp to somewhere on the first road
|
||||
let road = map.get_r(self.first);
|
||||
|
@ -11,7 +11,7 @@ use ezgui::{
|
||||
};
|
||||
|
||||
// TODO Rethink this API.
|
||||
pub fn tool_panel(ctx: &EventCtx, extra_buttons: Vec<ManagedWidget>) -> Composite {
|
||||
pub fn tool_panel(ctx: &mut EventCtx, extra_buttons: Vec<ManagedWidget>) -> Composite {
|
||||
let mut row = vec![
|
||||
// TODO Maybe this is confusing -- it doesn't jump to the title screen necessarily.
|
||||
// Caller has to handle this one
|
||||
@ -105,7 +105,7 @@ pub fn tool_panel(ctx: &EventCtx, extra_buttons: Vec<ManagedWidget>) -> Composit
|
||||
)
|
||||
}
|
||||
|
||||
pub fn edit_map_panel(ctx: &EventCtx, ui: &UI, gameplay: GameplayMode) -> Composite {
|
||||
pub fn edit_map_panel(ctx: &mut EventCtx, ui: &UI, gameplay: GameplayMode) -> Composite {
|
||||
Composite::new(ezgui::Composite::aligned(
|
||||
ctx,
|
||||
(HorizontalAlignment::Center, VerticalAlignment::Top),
|
||||
|
@ -59,7 +59,7 @@ impl State for RouteExplorer {
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
// We don't really care about setting current_selection to the current step; drawing covers
|
||||
// it up anyway.
|
||||
|
@ -112,7 +112,7 @@ impl State for TripExplorer {
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
self.menu.event(ctx);
|
||||
if self.menu.action("quit") {
|
||||
|
@ -127,7 +127,7 @@ struct ShowTrafficSignal {
|
||||
impl State for ShowTrafficSignal {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
self.menu.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
if self.menu.action("quit") {
|
||||
return Transition::Pop;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ impl State for Floodfiller {
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
self.menu.event(ctx);
|
||||
if self.menu.action("quit") {
|
||||
|
@ -93,7 +93,7 @@ impl State for DebugMode {
|
||||
}
|
||||
self.menu.event(ctx);
|
||||
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
self.associated.event(ui);
|
||||
|
||||
if self.menu.action("save sim state") {
|
||||
|
@ -159,7 +159,7 @@ impl PolygonDebugger {
|
||||
|
||||
impl State for PolygonDebugger {
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if let Some((evmode, _)) = self.slider.event(ctx) {
|
||||
Transition::KeepWithMode(evmode)
|
||||
|
@ -34,7 +34,7 @@ pub struct EditMode {
|
||||
}
|
||||
|
||||
impl EditMode {
|
||||
pub fn new(ctx: &EventCtx, ui: &mut UI, mode: GameplayMode) -> EditMode {
|
||||
pub fn new(ctx: &mut EventCtx, ui: &mut UI, mode: GameplayMode) -> EditMode {
|
||||
let suspended_sim = ui.primary.clear_sim();
|
||||
EditMode {
|
||||
common: CommonState::new(),
|
||||
@ -137,7 +137,7 @@ impl State for EditMode {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
// It only makes sense to mouseover lanes while painting them.
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
|
@ -52,7 +52,7 @@ impl StopSignEditor {
|
||||
impl State for StopSignEditor {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
self.menu.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if ctx.redo_mouseover() {
|
||||
self.selected_sign = None;
|
||||
|
@ -95,7 +95,7 @@ impl State for TrafficSignalEditor {
|
||||
|
||||
self.menu.set_info(ctx, txt);
|
||||
}
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
self.diagram.event(ctx, ui, &mut self.menu);
|
||||
|
||||
if ctx.redo_mouseover() {
|
||||
@ -509,7 +509,7 @@ struct PreviewTrafficSignal {
|
||||
}
|
||||
|
||||
impl PreviewTrafficSignal {
|
||||
fn new(ctx: &EventCtx, ui: &UI) -> PreviewTrafficSignal {
|
||||
fn new(ctx: &mut EventCtx, ui: &UI) -> PreviewTrafficSignal {
|
||||
PreviewTrafficSignal {
|
||||
menu: ModalMenu::new(
|
||||
"Preview traffic signal",
|
||||
@ -525,7 +525,7 @@ impl PreviewTrafficSignal {
|
||||
|
||||
impl State for PreviewTrafficSignal {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
self.menu.event(ctx);
|
||||
if self.menu.action("back to editing") {
|
||||
ui.primary.clear_sim();
|
||||
|
@ -212,7 +212,6 @@ impl WizardState {
|
||||
|
||||
impl State for WizardState {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if let Some(t) = (self.cb)(&mut self.wizard, ctx, ui) {
|
||||
return t;
|
||||
} else if self.wizard.aborted() {
|
||||
|
@ -104,7 +104,7 @@ impl State for TripsVisualizer {
|
||||
self.menu.set_info(ctx, txt);
|
||||
}
|
||||
self.menu.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
layout::stack_vertically(
|
||||
layout::ContainerOrientation::TopRight,
|
||||
ctx,
|
||||
|
@ -59,7 +59,7 @@ impl TripsVisualizer {
|
||||
impl State for TripsVisualizer {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
self.slider.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
|
@ -36,7 +36,7 @@ impl MissionEditMode {
|
||||
impl State for MissionEditMode {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
self.menu.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if self.menu.action("quit") {
|
||||
return Transition::Pop;
|
||||
|
@ -21,7 +21,7 @@ impl NeighborhoodPicker {
|
||||
|
||||
impl State for NeighborhoodPicker {
|
||||
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if let Some(n) = pick_neighborhood(&ui.primary.map, self.wizard.wrap(ctx)) {
|
||||
self.wizard = Wizard::new();
|
||||
@ -75,7 +75,7 @@ impl State for NeighborhoodEditor {
|
||||
let gps_bounds = ui.primary.map.get_gps_bounds();
|
||||
|
||||
self.menu.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if self.moving_pt {
|
||||
if let Some(pt) = ctx
|
||||
|
@ -161,7 +161,7 @@ impl State for ScenarioManager {
|
||||
self.menu.set_info(ctx, txt);
|
||||
}
|
||||
self.menu.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ impl State for TitleScreen {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_menu(ctx: &EventCtx, ui: &UI) -> Box<dyn State> {
|
||||
pub fn main_menu(ctx: &mut EventCtx, ui: &UI) -> Box<dyn State> {
|
||||
let mut col = Vec::new();
|
||||
|
||||
col.push(ManagedWidget::row(vec![
|
||||
@ -169,7 +169,7 @@ pub fn main_menu(ctx: &EventCtx, ui: &UI) -> Box<dyn State> {
|
||||
ManagedGUIState::new(c)
|
||||
}
|
||||
|
||||
fn about(ctx: &EventCtx) -> Box<dyn State> {
|
||||
fn about(ctx: &mut EventCtx) -> Box<dyn State> {
|
||||
let mut col = Vec::new();
|
||||
|
||||
col.push(Composite::svg_button(
|
||||
|
@ -164,7 +164,7 @@ impl TrafficSignalDiagram {
|
||||
i: IntersectionID,
|
||||
current_phase: usize,
|
||||
ui: &UI,
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
) -> TrafficSignalDiagram {
|
||||
TrafficSignalDiagram {
|
||||
i,
|
||||
@ -192,7 +192,7 @@ impl TrafficSignalDiagram {
|
||||
}
|
||||
}
|
||||
|
||||
fn change_phase(&mut self, idx: usize, ui: &UI, ctx: &EventCtx) {
|
||||
fn change_phase(&mut self, idx: usize, ui: &UI, ctx: &mut EventCtx) {
|
||||
if self.current_phase != idx {
|
||||
let preserve_scroll = self.composite.preserve_scroll(ctx);
|
||||
self.current_phase = idx;
|
||||
@ -210,7 +210,7 @@ impl TrafficSignalDiagram {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_diagram(i: IntersectionID, selected: usize, ui: &UI, ctx: &EventCtx) -> Composite {
|
||||
fn make_diagram(i: IntersectionID, selected: usize, ui: &UI, ctx: &mut EventCtx) -> Composite {
|
||||
// Slightly inaccurate -- the turn rendering may slightly exceed the intersection polygon --
|
||||
// but this is close enough.
|
||||
let bounds = ui.primary.map.get_i(i).polygon.get_bounds();
|
||||
|
@ -153,7 +153,7 @@ impl State for BusRouteExplorer {
|
||||
// TODO Or use what debug mode is showing?
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if let Some((evmode, done_warping)) = self.slider.event(ctx) {
|
||||
if done_warping {
|
||||
|
@ -23,7 +23,7 @@ pub enum Tab {
|
||||
}
|
||||
|
||||
// Oh the dashboards melted, but we still had the radio
|
||||
pub fn make(ctx: &EventCtx, ui: &UI, tab: Tab) -> Box<dyn State> {
|
||||
pub fn make(ctx: &mut EventCtx, ui: &UI, tab: Tab) -> Box<dyn State> {
|
||||
let tab_data = vec![
|
||||
(Tab::FinishedTripsSummary, "Finished trips summary"),
|
||||
(
|
||||
|
@ -15,7 +15,7 @@ pub struct CreateGridlock {
|
||||
}
|
||||
|
||||
impl CreateGridlock {
|
||||
pub fn new(ctx: &EventCtx, ui: &UI) -> (ModalMenu, Composite, Box<dyn GameplayState>) {
|
||||
pub fn new(ctx: &mut EventCtx, ui: &UI) -> (ModalMenu, Composite, Box<dyn GameplayState>) {
|
||||
(
|
||||
ModalMenu::new(
|
||||
"Cause gridlock",
|
||||
|
@ -17,7 +17,7 @@ pub struct FasterTrips {
|
||||
impl FasterTrips {
|
||||
pub fn new(
|
||||
trip_mode: TripMode,
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
ui: &UI,
|
||||
) -> (ModalMenu, Composite, Box<dyn GameplayState>) {
|
||||
(
|
||||
|
@ -17,7 +17,7 @@ pub struct FixTrafficSignals {
|
||||
|
||||
impl FixTrafficSignals {
|
||||
pub fn new(
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
ui: &UI,
|
||||
mode: GameplayMode,
|
||||
) -> (ModalMenu, Composite, Box<dyn GameplayState>) {
|
||||
|
@ -19,7 +19,7 @@ pub struct Freeform {
|
||||
}
|
||||
|
||||
impl Freeform {
|
||||
pub fn new(ctx: &EventCtx, ui: &UI) -> (ModalMenu, Composite, Box<dyn GameplayState>) {
|
||||
pub fn new(ctx: &mut EventCtx, ui: &UI) -> (ModalMenu, Composite, Box<dyn GameplayState>) {
|
||||
(
|
||||
ModalMenu::new("Freeform mode", vec![(hotkey(Key::H), "help")], ctx),
|
||||
freeform_controller(ctx, ui, GameplayMode::Freeform, "empty scenario"),
|
||||
@ -71,7 +71,7 @@ impl GameplayState for Freeform {
|
||||
}
|
||||
|
||||
pub fn freeform_controller(
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
ui: &UI,
|
||||
gameplay: GameplayMode,
|
||||
scenario_name: &str,
|
||||
|
@ -24,7 +24,7 @@ pub struct OptimizeBus {
|
||||
impl OptimizeBus {
|
||||
pub fn new(
|
||||
route_name: String,
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
ui: &UI,
|
||||
) -> (ModalMenu, crate::managed::Composite, Box<dyn GameplayState>) {
|
||||
let route = ui.primary.map.get_bus_route(&route_name).unwrap();
|
||||
|
@ -11,7 +11,7 @@ pub struct PlayScenario;
|
||||
impl PlayScenario {
|
||||
pub fn new(
|
||||
name: &String,
|
||||
ctx: &EventCtx,
|
||||
ctx: &mut EventCtx,
|
||||
ui: &UI,
|
||||
) -> (ModalMenu, Composite, Box<dyn GameplayState>) {
|
||||
(
|
||||
|
@ -174,7 +174,7 @@ impl State for AgentSpawner {
|
||||
return Transition::Pop;
|
||||
}
|
||||
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
@ -552,7 +552,7 @@ impl State for SpawnManyAgents {
|
||||
return Transition::Pop;
|
||||
}
|
||||
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ impl State for SandboxMode {
|
||||
return t;
|
||||
}
|
||||
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
if ctx.redo_mouseover() {
|
||||
ui.recalculate_current_selection(ctx);
|
||||
}
|
||||
@ -270,7 +270,7 @@ struct AgentMeter {
|
||||
}
|
||||
|
||||
impl AgentMeter {
|
||||
pub fn new(ctx: &EventCtx, ui: &UI) -> AgentMeter {
|
||||
pub fn new(ctx: &mut EventCtx, ui: &UI) -> AgentMeter {
|
||||
let (active, unfinished, by_mode) = ui.primary.sim.num_trips();
|
||||
|
||||
let composite = Composite::aligned(
|
||||
|
@ -135,7 +135,7 @@ impl Overlays {
|
||||
}
|
||||
|
||||
impl Overlays {
|
||||
fn parking_availability(ctx: &EventCtx, ui: &UI) -> Overlays {
|
||||
fn parking_availability(ctx: &mut EventCtx, ui: &UI) -> Overlays {
|
||||
let (filled_spots, avail_spots) = ui.primary.sim.get_all_parking_spots();
|
||||
let mut txt = Text::from(Line("parking availability"));
|
||||
txt.add(Line(format!(
|
||||
@ -207,7 +207,7 @@ impl Overlays {
|
||||
Overlays::ParkingAvailability(ui.primary.sim.time(), colorer.build(ctx, ui))
|
||||
}
|
||||
|
||||
pub fn intersection_delay(ctx: &EventCtx, ui: &UI) -> Overlays {
|
||||
pub fn intersection_delay(ctx: &mut EventCtx, ui: &UI) -> Overlays {
|
||||
let fast = Color::hex("#7FFA4D");
|
||||
let meh = Color::hex("#F4DA22");
|
||||
let slow = Color::hex("#EB5757");
|
||||
@ -239,7 +239,7 @@ impl Overlays {
|
||||
Overlays::IntersectionDelay(ui.primary.sim.time(), colorer.build(ctx, ui))
|
||||
}
|
||||
|
||||
fn cumulative_throughput(ctx: &EventCtx, ui: &UI) -> Overlays {
|
||||
fn cumulative_throughput(ctx: &mut EventCtx, ui: &UI) -> Overlays {
|
||||
let light = Color::hex("#7FFA4D");
|
||||
let medium = Color::hex("#F4DA22");
|
||||
let heavy = Color::hex("#EB5757");
|
||||
@ -293,7 +293,7 @@ impl Overlays {
|
||||
Overlays::CumulativeThroughput(ui.primary.sim.time(), colorer.build(ctx, ui))
|
||||
}
|
||||
|
||||
fn bike_network(ctx: &EventCtx, ui: &UI) -> Overlays {
|
||||
fn bike_network(ctx: &mut EventCtx, ui: &UI) -> Overlays {
|
||||
let color = Color::hex("#7FFA4D");
|
||||
let mut colorer = ColorerBuilder::new(
|
||||
Text::from(Line("bike networks")),
|
||||
@ -307,7 +307,7 @@ impl Overlays {
|
||||
Overlays::BikeNetwork(colorer.build(ctx, ui))
|
||||
}
|
||||
|
||||
fn bus_network(ctx: &EventCtx, ui: &UI) -> Overlays {
|
||||
fn bus_network(ctx: &mut EventCtx, ui: &UI) -> Overlays {
|
||||
let color = Color::hex("#4CA7E9");
|
||||
let mut colorer =
|
||||
ColorerBuilder::new(Text::from(Line("bus networks")), vec![("bus lanes", color)]);
|
||||
@ -319,7 +319,7 @@ impl Overlays {
|
||||
Overlays::BusNetwork(colorer.build(ctx, ui))
|
||||
}
|
||||
|
||||
pub fn finished_trips_histogram(ctx: &EventCtx, ui: &UI) -> Overlays {
|
||||
pub fn finished_trips_histogram(ctx: &mut EventCtx, ui: &UI) -> Overlays {
|
||||
let now = ui.primary.sim.time();
|
||||
Overlays::FinishedTripsHistogram(
|
||||
now,
|
||||
@ -341,7 +341,7 @@ impl Overlays {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn intersection_demand(i: IntersectionID, ctx: &EventCtx, ui: &UI) -> Overlays {
|
||||
pub fn intersection_demand(i: IntersectionID, ctx: &mut EventCtx, ui: &UI) -> Overlays {
|
||||
let mut batch = GeomBatch::new();
|
||||
|
||||
let mut total_demand = 0;
|
||||
|
@ -28,7 +28,12 @@ enum SpeedState {
|
||||
}
|
||||
|
||||
impl SpeedControls {
|
||||
fn make_panel(ctx: &EventCtx, paused: bool, actual_speed: &str, slider: Slider) -> Composite {
|
||||
fn make_panel(
|
||||
ctx: &mut EventCtx,
|
||||
paused: bool,
|
||||
actual_speed: &str,
|
||||
slider: Slider,
|
||||
) -> Composite {
|
||||
let mut row = Vec::new();
|
||||
if paused {
|
||||
row.push(ManagedWidget::btn(Button::rectangle_svg(
|
||||
@ -148,7 +153,7 @@ impl SpeedControls {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(ctx: &EventCtx, ui: &UI) -> SpeedControls {
|
||||
pub fn new(ctx: &mut EventCtx, ui: &UI) -> SpeedControls {
|
||||
// 10 sim minutes / real second normally, or 1 sim hour / real second for dev mode
|
||||
let speed_cap: f64 = if ui.opts.dev { 3600.0 } else { 600.0 };
|
||||
let mut slider = Slider::horizontal(ctx, 160.0);
|
||||
@ -264,7 +269,7 @@ impl SpeedControls {
|
||||
self.composite.draw(g);
|
||||
}
|
||||
|
||||
pub fn pause(&mut self, ctx: &EventCtx) {
|
||||
pub fn pause(&mut self, ctx: &mut EventCtx) {
|
||||
if !self.is_paused() {
|
||||
self.state = SpeedState::Paused;
|
||||
self.composite =
|
||||
@ -361,7 +366,7 @@ pub struct TimePanel {
|
||||
}
|
||||
|
||||
impl TimePanel {
|
||||
pub fn new(ctx: &EventCtx, ui: &UI) -> TimePanel {
|
||||
pub fn new(ctx: &mut EventCtx, ui: &UI) -> TimePanel {
|
||||
TimePanel {
|
||||
time: ui.primary.sim.time(),
|
||||
composite: ezgui::Composite::aligned(
|
||||
|
@ -35,7 +35,7 @@ impl State for TutorialMode {
|
||||
}
|
||||
self.menu.set_info(ctx, txt);
|
||||
self.menu.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if self.menu.action("quit") {
|
||||
return Transition::Pop;
|
||||
@ -68,7 +68,7 @@ impl State for Part2 {
|
||||
}
|
||||
self.menu.set_info(ctx, txt);
|
||||
self.menu.event(ctx);
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
|
||||
if self.menu.action("quit") {
|
||||
return Transition::Pop;
|
||||
|
@ -122,7 +122,7 @@ impl UI {
|
||||
|
||||
impl GUI for UI {
|
||||
fn event(&mut self, ctx: &mut EventCtx) -> EventLoopMode {
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
ctx.canvas_movement();
|
||||
self.menu.event(ctx);
|
||||
if ctx.redo_mouseover() {
|
||||
self.model.world.handle_mouseover(ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user