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:
Dustin Carlino 2020-01-07 11:43:34 -06:00
parent eb9050777b
commit 0ad371525b
46 changed files with 132 additions and 99 deletions

View File

@ -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() {

View File

@ -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()
}

View File

@ -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
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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![

View File

@ -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),

View File

@ -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);

View File

@ -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),

View File

@ -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);

View File

@ -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),

View File

@ -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.

View File

@ -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") {

View File

@ -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;
}

View File

@ -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") {

View File

@ -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") {

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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() {

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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(

View File

@ -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();

View File

@ -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 {

View File

@ -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"),
(

View File

@ -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",

View File

@ -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>) {
(

View File

@ -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>) {

View File

@ -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,

View File

@ -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();

View File

@ -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>) {
(

View File

@ -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);
}

View File

@ -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(

View File

@ -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;

View File

@ -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(

View File

@ -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;

View File

@ -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);